SOURCE

function allReadyEdit() {
    var mstform = Ext.getCmp('p_form0000700102_m');
    var dgrid = Ext.getCmp('p_form0000700102_dgrid');
    var dgrid1 = Ext.getCmp('p_form0000700102_d1grid');
    var dstore = dgrid.store;
    var dstore1 = dgrid1.store;
    var Toolbar = Ext.getCmp('toolbar');
    mstform.getItem('empidmul').setVisible(false);
    mstform.getItem('pc').setVisible(false)
    mstform.getItem('tr_type').setVisible(false)
    mstform.getItem('tr_num').setVisible(false)
    mstform.getItem('tr_date').setVisible(false)
    mstform.getItem('voucher_flag').setVisible(false)
    dgrid.hideColumn('checkboxcol_1', true);
    dgrid.hideColumn('ykkt_name', true);
    dgrid.hideColumn('tr_date', true);
    dgrid.hideColumn('sydw1', true);
    //dgrid.hideColumn('textcol_2', true);
    const holidayRanges = [
        { start: '2025-04-03', end: '2025-04-06' }, // 清明
        { start: '2025-04-30', end: '2025-05-05' }, // 五一
        { start: '2025-05-30', end: '2025-06-02' }  // 端午
    ];
    const workWeekends = [
        '2025-04-27', // 国庆节调休上班
        '2023-10-08'  // 国庆节调休上班
    ];
    mstform.on('dataready', function () {
        Toolbar.insert(5, { itemId: "jc", text: "基础数据获取", width: this.itemWidth, iconCls: "icon-refuse" });   //指定位置插入按钮
        Toolbar.insert(6, { itemId: "ts", text: "考勤天数设置", width: this.itemWidth, iconCls: "icon-New" });   //指定位置插入按钮
        Toolbar.insert(8, { itemId: "js", text: "薪资计算", width: this.itemWidth, iconCls: "icon-New" });   //指定位置插入按钮
        Toolbar.insert(9, { itemId: "yc", text: "显示/隐藏", width: this.itemWidth, iconCls: "icon-New" });   //指定位置插入按钮
        var id = mstform.getItem('fillpsn').getValue();
        if ($appinfo.userID == id || $appinfo.userID == '806210625000001') {
            Toolbar.get('jc').show();
            Toolbar.get('ts').show();
            Toolbar.get('js').show();
            Toolbar.get('yc').hide();
        } else {
            Toolbar.get('jc').hide();
            Toolbar.get('ts').hide();
            Toolbar.get('js').hide();
            Toolbar.get('yc').show();
        }
        Toolbar.get('js').on('click', function () {
            Ext.Msg.wait("正在处理数据...", "请稍候");

            // 1. 提前缓存所有数据(减少DOM访问)
            var storeData = dgrid.getStore().getRange();
            var totalCount = storeData.length;
            var batchSize = 50; // 增大批次大小

            // 2. 主处理函数(避免闭包内重复声明变量)
            function processBatch(index) {
                var end = Math.min(index + batchSize, totalCount);

                for (; index < end; index++) {
                    var record = storeData[index];
                    if (record.get('checkboxcol_2') != 1) continue;

                    // 3. 一次性获取所有字段(减少get()调用次数)
                    var fields = {
                        gzbz: record.get('gzbz') || 0,
                        byts: record.get('byts') || 0,
                        jxts: record.get('jxts') || 1, // 确保至少为1,避免除零
                        u_jxbl: record.get('u_jxbl') || 0,
                        zcbz: record.get('zcbz') || 0,
                        zwbz: record.get('zwbz') || 0,
                        qtbz: record.get('qtbz') || 0,
                        xlbz: record.get('xlbz') || 0,
                        dnbz: record.get('u_dnbz') || 0,
                        jj: record.get('jj') || 0,
                        qjkk: record.get('qjkk') || 0,
                        grhj: record.get('grhj') || 0,
                        gjjgr: record.get('gjjgr') || 0,
                        u_grsdr: record.get('u_grsdr') || 0,
                        u_qtkk: record.get('u_qtkk') || 0,
                        numericcol_4: record.get('numericcol_4') || 0,
                        pc: record.get('zz') || 0,
                        jxbckk: record.get('numericcol_5') || 0,
                        ghhyf: record.get('numericcol_2') || 0
                    };

                    // 计算逻辑(每一步四舍五入,但用 parseFloat 保证数值运算)
                    var qjgz = parseFloat((fields.gzbz * 0.3 * fields.numericcol_4 / fields.jxts).toFixed(2));
                    var ratio = fields.byts / fields.jxts;
                    var jbgz = parseFloat((fields.gzbz * 0.3 * ratio + qjgz).toFixed(2));
                    var gwgz = parseFloat((fields.gzbz * (0.7 - fields.u_jxbl) * ratio).toFixed(2));
                    var jxgz = parseFloat((fields.gzbz * fields.u_jxbl * ratio).toFixed(2));
                    var bzhj = parseFloat((fields.zcbz + fields.zwbz + fields.qtbz + fields.xlbz + fields.dnbz).toFixed(2));
                    var yfhj = parseFloat((jbgz + gwgz + jxgz + bzhj + fields.jj - fields.qjkk).toFixed(2));
                    var ynshj = parseFloat((yfhj - fields.grhj - fields.gjjgr).toFixed(2));
                    var jxgskk = parseFloat((jxgz + fields.jxbckk).toFixed(2));
                    if (fields.pc == '537200313000030' || fields.pc == '537200315000048' || fields.pc == '806221125062004' || fields.pc == '537200315000008'
                        || fields.pc == '537200315000070' || fields.pc == '537200313000037' || fields.pc == '537200315000019' || fields.pc == '614000000000034' || fields.pc == '614000000000007'
                        || fields.pc == '537200313000036' || fields.pc == '537200315000005' || fields.pc == '537200313000049') {
                        var ghhyf = fields.ghhyf;
                    } else { var ghhyf = parseFloat((jbgz * 0.005).toFixed(2)); }
                    // 5. 一次性设置所有字段(减少set()调用开销)
                    record.set({
                        'jbgz': jbgz,
                        'gwgz': gwgz,
                        'jxgz': jxgz,
                        'bzhj': bzhj,
                        'yfhj': yfhj,
                        'ynshj': ynshj,
                        'u_jxgskk': jxgskk,
                        'numericcol_2': ghhyf,
                        'u_sfhj': ynshj - fields.u_grsdr - jxgskk - fields.u_qtkk - ghhyf
                    });
                }

                // 6. 使用requestAnimationFrame优化UI更新
                if (index < totalCount) {
                    requestAnimationFrame(() => processBatch(index));
                } else {
                    dgrid.getView().refresh();
                    Ext.Msg.hide();
                }
            }

            // 7. 延迟启动以确保等待框显示
            setTimeout(() => processBatch(0), 50);
        });

        // 1. 创建菜单
        var toolMenu = Ext.create('Ext.menu.Menu', {
            items: [{
                text: '一键选择/取消',
                itemId: 'xzqx',
                handler: function () {
                    processBatchUpdate('checkboxcol_2');
                }
            }, {
                text: '一键赋值系数',
                itemId: 'fzxs',
                handler: function () {
                    processBatchUpdate('numericcol_3');
                }
            }]
        });

        // 2. 创建按钮并绑定菜单(兼容所有版本)
        var assignBtn = Ext.create('Ext.button.Button', {
            itemId: "xz",
            text: "一键赋值",
            width: this.itemWidth,
            iconCls: "icon-New",
            menu: toolMenu  // 标准方式
        });

        Toolbar.insert(9, assignBtn);

        // 4. 通用批量更新函数
        function processBatchUpdate(field) {
            var store = dgrid.getStore();
            var records = store.getRange();
            var value = records[0].get(field);

            Ext.Msg.wait("处理中...", "请稍候");
            store.suspendEvents();

            Ext.Array.each(records, function (record) {
                record.set(field, field == 'checkboxcol_2' ? (value == '0' ? 1 : 0) : value);
            });

            store.resumeEvents();
            dgrid.getView().refresh();
            Ext.Msg.hide();
        }

        Toolbar.get('ts').on('click', function () {
            var nd = mstform.getItem('nd').getValue();
            var yf = mstform.getItem('yf').getValue();
            var date = timestampToTime(mstform.getItem('datetimecol_2').getValue());
            var dt = timestampToTime(mstform.getItem('datetimecol_1').getValue());

            // 验证输入
            if (Ext.isEmpty(nd)) {
                Ext.Msg.alert('提示', '请先选择年度!');
                return false;
            };
            if (Ext.isEmpty(Ext.getCmp('yf').getValue())) {
                Ext.Msg.alert('提示', '请先输入月份!');
                return false;
            };

            // 显示等待提示
            Ext.Msg.wait("正在处理数据...", "请稍候");

            // 定义共享变量
            var map_lzrq = new Map();
            var map_lzry = new Map();
            var map_kqtstj = new Map();
            var map_qjrqpd = new Map();
            var fzts_tmp = 0;
            var kqfz2 = 0;

            // 并行执行所有服务器请求
            Promise.all([
                new Promise((resolve) => {
                    callServer('lzrq', [{ 'appdt': dt, 'date': date }], function (res) {
                        res.record.forEach(element => {
                            var arr = [element.appdtt, element.chgtype, element.phiddept, element.dept];
                            map_lzrq.set(element.phid, arr);
                        });
                        resolve();
                    });
                }),
                new Promise((resolve) => {
                    callServer('lzry', [{ 'appdt': dt, 'date': date }], function (res) {
                        res.record.forEach(element => {
                            map_lzry.set(element.phid, element.appdtt);
                        });
                        resolve();
                    });
                }),
                new Promise((resolve) => {
                    callServer('qijqpd', [{ 'nd': nd, 'yf': yf }], function (res) {
                        if (res.record.length > 0) {
                            res.record.forEach(element => {
                                map_qjrqpd.set(element.ry, [element.factbdt, element.factend, element.holitype]);
                            });
                        }
                        resolve();
                    });
                }),
                new Promise((resolve) => {
                    callServer('kqtstj', [{ 'nd': nd, 'yf': yf }], function (res) {
                        if (res.record.length > 0) {
                            res.record.forEach(element => {
                                map_kqtstj.set(element.ry, [element.aa, element.kgts, element.qjts]);
                            });
                        }
                        resolve();
                    });
                }),
                new Promise((resolve) => {
                    callServer('kqfz', [{ 'nd': nd, 'yf': yf }], function (res) {
                        if (res.record.length > 0) {
                            fzts_tmp = res.record[0].numericcol_1;
                        }
                        resolve();
                    });
                })
            ]).then(() => {
                // 所有数据加载完成后开始处理
                var a = dgrid.getStore().getRange(0, dstore.getCount() - 1);
                var index = 0;
                var batchSize = 10; // 每批处理10条记录

                function processBatch() {
                    var end = Math.min(index + batchSize, dstore.getCount());

                    for (; index < end; index++) {
                        if (a[index].get('checkboxcol_2') == 1) {
                            var id = a[index].get('checkboxcol_1');
                            var ry = a[index].get('empid');
                            var rymb = ry + a[index].get('deptid');
                            var sfz = a[index].get('textcol_1');
                            var cdt = a[index].get('datetimecol_1');
                            var syqygzt = a[index].get('u_ygzt');
                            if (id == '') {
                                var ts1, ts2, qjts, ts3, ts4, fzts = 0, ts5, fztsf = 0;

                                if (map_kqtstj.get(rymb) && syqygzt != '试用') {
                                    ts1 = map_kqtstj.get(rymb)[0]; // aa
                                    ts2 = map_kqtstj.get(rymb)[1]; // kgts
                                    qjts = map_kqtstj.get(rymb)[2]; // qjts
                                } else {
                                    callServer('syqyglx', [{ 'rymb': rymb, 'nd': nd, 'yf': yf }], function (res) {
                                        if (res) {
                                            ts1 = res.record[0].aa; // aa
                                            ts2 = res.record[0].kgts; // kgts
                                            qjts = res.record[0].qjts; // qjts
                                        }
                                    });
                                }

                                if (map_qjrqpd.get(ry)) {
                                    ts3 = new Date(map_qjrqpd.get(ry)[0]);
                                    ts4 = new Date(map_qjrqpd.get(ry)[1]);
                                    ts5 = map_qjrqpd.get(ry)[2];
                                }

                                if (cdt > timestampToTime(dt)) {
                                    fzts = countMonthSpecialDays(timestampToTime(cdt), holidayRanges, workWeekends, "after");
                                    kqfz2 = 0; // 需要根据实际情况调整
                                } else if (map_lzrq.get(ry)) {
                                    if (map_lzrq.get(ry)[2] == a[index].get('deptid')) {
                                        fzts = countMonthSpecialDays(map_lzrq.get(ry)[0], holidayRanges, workWeekends, "before");
                                    } else if (map_lzrq.get(ry)[3] == a[index].get('deptid')) {
                                        fzts = countMonthSpecialDays(map_lzrq.get(ry)[0], holidayRanges, workWeekends, "after");
                                    }
                                    if (map_lzrq.get(ry)[1] != 6) {
                                        if ((ts1 || 0) - kqfz2 + fzts < a[index].get('jxts') / 2) {
                                            a[index].set('yldw', 0);
                                            a[index].set('ylgr', 0);
                                            a[index].set('sydw', 0);
                                            a[index].set('sygr', 0);
                                            a[index].set('yldw1', 0);
                                            a[index].set('ylgr1', 0);
                                            a[index].set('gsdw', 0);
                                            a[index].set('sydw1', 0);
                                            a[index].set('dedw', 0);
                                            a[index].set('degr', 0);
                                            a[index].set('dwhj', 0);
                                            a[index].set('grhj', 0);
                                            a[index].set('qtbz', 0);
                                            a[index].set('u_dnbz', 0);
                                            a[index].set('xlbz', 0);
                                            a[index].set('u_grsdr', 0);
                                            a[index].set('zcbz', 0);
                                            a[index].set('gjjdw', 0);
                                            a[index].set('gjjgr', 0);
                                        }
                                    }
                                    kqfz2 = 0;
                                } else if (map_lzry.get(ry)) {
                                    fzts = countMonthSpecialDays(map_lzry.get(ry), holidayRanges, workWeekends, "before");
                                }
                                else {
                                    if ((!ts3 && !ts4) || ts5 == 8 || ts5 == 5) {
                                        fzts = countMonthSpecialDays(dt, holidayRanges, workWeekends, "all");
                                    } else if (timestampToTime(ts3) < dt && timestampToTime(ts4) > date) {
                                        fzts = 0;
                                    } else if (timestampToTime(ts3) > dt && timestampToTime(ts4) > date) {
                                        fzts = countMonthSpecialDays(formatDate(ts3), holidayRanges, workWeekends, "before");
                                    } else if (timestampToTime(ts3) > dt && timestampToTime(ts4) < date) {
                                        fzts = countMonthSpecialDays(formatDate(ts4), holidayRanges, workWeekends, "after") + countMonthSpecialDays(formatDate(ts3), holidayRanges, workWeekends, "before");
                                    }
                                    else {
                                        fzts = countMonthSpecialDays(formatDate(ts4), holidayRanges, workWeekends, "after");
                                    }
                                    if (ts5 == 8 || ts5 == 5) {
                                        fztsf = countMonthSpecialDays(formatDate(ts3), holidayRanges, workWeekends, "all", formatDate(ts4))
                                    }
                                    kqfz2 = 0;
                                }

                                a[index].set('byts', (ts1 || 0) - kqfz2 + fzts - fztsf);
                                a[index].set('numericcol_4', qjts || 0);
                                a[index].set('numericcol_1', (ts1 || 0));
                                ts3 = ''; ts4 = '', ts5 = ''
                            }
                        }
                    }

                    if (index < dstore.getCount()) {
                        setTimeout(processBatch, 0);
                    } else {
                        dgrid.getView().refresh();
                        Ext.Msg.hide();
                    }
                }

                processBatch();
            }).catch((error) => {
                Ext.Msg.hide();
                Ext.Msg.alert('错误', '数据处理过程中发生错误: ' + error.message);
            });
        });

        Toolbar.items.get('jc').on('click', async function () {
            try {
                // 显示等待提示
                Ext.Msg.wait("正在处理数据...", "请稍候");

                var nd = mstform.getItem('nd').getValue();
                var yf = mstform.getItem('yf').getValue();
                var date = timestampToTime(mstform.getItem('datetimecol_2').getValue());
                var date1 = timestampToTime(mstform.getItem('datetimecol_1').getValue());

                // 验证输入
                if (Ext.isEmpty(nd)) {
                    Ext.Msg.hide();
                    Ext.Msg.alert('提示', '请先选择年度!');
                    return false;
                }
                if (Ext.isEmpty(Ext.getCmp('yf').getValue())) {
                    Ext.Msg.hide();
                    Ext.Msg.alert('提示', '请先输入月份!');
                    return false;
                }

                // 定义所有映射表
                var map_lzrq = new Map();
                var map_yglx = new Map();
                var map_gzbz = new Map();
                var map_sbxx = new Map();
                var map_gjjxx = new Map();
                var map_gskk = new Map();
                var map_zcbz = new Map();
                var map_cbtj = new Map();
                var map_zgdn = new Map();

                // 将callServer封装为Promise
                function callServerPromise(service, params) {
                    return new Promise((resolve) => {
                        callServer(service, params, function (res) {
                            resolve(res);
                        });
                    });
                }

                // 并行加载所有数据
                await Promise.all([
                    // 查询工资标准
                    callServerPromise('gzbz', [{}]).then(res => {
                        res.record.forEach(element => {
                            map_gzbz.set(element.must_phid, element.salary);
                        });
                    }),

                    // 查询参保统计
                    callServerPromise('cbtj', [{ 'nd': nd, 'yf': yf }]).then(res => {
                        res.record.forEach(element => {
                            map_cbtj.set(element.ry, element.cb);
                        });
                    }),

                    // 查询员工类型
                    callServerPromise('yglx', [{}]).then(res => {
                        res.record.forEach(element => {
                            map_yglx.set(element.phid, element.emptype);
                        });
                    }),

                    // 查询社保信息
                    callServerPromise('sbxx', [{ 'nd': nd, 'yf': yf }]).then(res => {
                        res.record.forEach(element => {
                            const normalizedSfz = element.sfz.replace(/x$/i, 'X');
                            map_sbxx.set(normalizedSfz, [
                                element.numericcol_1,
                                element.numericcol_2,
                                element.numericcol_3,
                                element.numericcol_4,
                                element.numericcol_5,
                                element.numericcol_6,
                                element.numericcol_7,
                                element.numericcol_8,
                                element.numericcol_9,
                                element.numericcol_10
                            ]);
                        });
                    }),

                    // 查询公积金信息
                    callServerPromise('gjjxx', [{ 'nd': nd, 'yf': yf }]).then(res => {
                        res.record.forEach(element => {
                            const normalizedSfz = element.sfz.replace(/x$/i, 'X');
                            map_gjjxx.set(normalizedSfz, [
                                element.numericcol_9,
                                element.numericcol_10
                            ]);
                        });
                    }),

                    // 查询个税扣款
                    callServerPromise('gskk', [{ 'nd': nd, 'yf': yf }]).then(res => {
                        res.record.forEach(element => {
                            const normalizedSfz = element.sfz.replace(/x$/i, 'X');
                            map_gskk.set(normalizedSfz, element.numericcol_1);
                        });
                    }),

                    // 查询职称补助
                    callServerPromise('zcbz', [{}]).then(res => {
                        res.record.forEach(element => {
                            const normalizedSfz = element.sfz.replace(/x$/i, 'X');
                            map_zcbz.set(normalizedSfz, element.amt);
                        });
                    }),

                    callServerPromise('zgbt', [{}]).then(res => {
                        res.record.forEach(element => {
                            map_zgdn.set(element.userhelp_1, element.textcol_1);
                        });
                    })
                ]);

                // 获取数据并分批处理
                var a = dgrid.getStore().getRange(0, dstore.getCount() - 1);
                var batchSize = 30; // 每批处理50条记录
                var currentIndex = 0;
                var dt = mstform.getItem('datetimecol_1').getValue();
                function processBatch() {
                    var endIndex = Math.min(currentIndex + batchSize, dstore.getCount());

                    for (; currentIndex < endIndex; currentIndex++) {
                        if (a[currentIndex].get('checkboxcol_2') == 1) {
                            var id = a[currentIndex].get('empid');
                            var sfz = a[currentIndex].get('textcol_1');
                            var ryxx = id + a[currentIndex].get('deptid');

                            // 设置工资标准
                            var gz = map_gzbz.get(id);
                            a[currentIndex].set('gzbz', gz * a[currentIndex].get('numericcol_3'));

                            // 设置绩效比例
                            var jx;
                            if ((map_yglx.get(id) == '806200805000002' || map_yglx.get(id) == '806200805000003') && a[currentIndex].get('u_ygzt') != '试用') {
                                jx = 0.2;
                            } else if (a[currentIndex].get('u_ygzt') != '试用' && map_yglx.get(id) != '806220111000002') {
                                jx = 0.1;
                            } else {
                                jx = 0;
                            }
                            a[currentIndex].set('u_jxbl', jx);

                            // 设置社保信息
                            if (map_sbxx.get(sfz)) {
                                var sb = map_sbxx.get(sfz);
                                a[currentIndex].set('yldw', sb[0]);
                                a[currentIndex].set('ylgr', sb[1]);
                                a[currentIndex].set('sydw', sb[2]);
                                a[currentIndex].set('sygr', sb[3]);
                                a[currentIndex].set('yldw1', sb[4]);
                                a[currentIndex].set('ylgr1', sb[5]);
                                a[currentIndex].set('gsdw', sb[6]);
                                a[currentIndex].set('sydw1', sb[7]);
                                a[currentIndex].set('dedw', sb[8]);
                                a[currentIndex].set('degr', sb[9]);
                                a[currentIndex].set('dwhj', sb[0] + sb[2] + sb[4] + sb[6] + sb[8]);
                                a[currentIndex].set('grhj', sb[1] + sb[3] + sb[5] + sb[9]);
                            }

                            // 设置参保统计
                            if (map_cbtj.get(ryxx)) {
                                a[currentIndex].set('xlbz', map_cbtj.get(ryxx));
                            } else {
                                a[currentIndex].set('xlbz', 0);
                            }
                            if (map_zgdn.get(id)) {
                                a[currentIndex].set('u_dnbz', 70);
                            }

                            // 设置工作天数
                            a[currentIndex].set('jxts', getDaysInMonth(dt));

                            // 设置个税扣款
                            if (map_gskk.get(sfz)) {
                                a[currentIndex].set('u_grsdr', map_gskk.get(sfz));
                            }

                            // 设置职称补助
                            if (map_zcbz.get(sfz)) {
                                a[currentIndex].set('zcbz', map_zcbz.get(sfz));
                            }
                            if (map_gjjxx.get(sfz)) {
                                var gjj = map_gjjxx.get(sfz);
                                a[currentIndex].set('gjjdw', gjj[0]);
                                a[currentIndex].set('gjjgr', gjj[1]);
                            }

                        }
                    }

                    // 如果还有数据,继续处理下一批
                    if (currentIndex < dstore.getCount()) {
                        setTimeout(processBatch, 0);
                    } else {
                        // 全部处理完成
                        dgrid.getView().refresh();
                        Ext.Msg.hide();
                    }
                }

                // 开始处理
                processBatch();

            } catch (error) {
                Ext.Msg.hide();
                Ext.Msg.alert('错误', '数据处理过程中发生错误: ' + error.message);
                console.error(error);
            }
        });

        Toolbar.get('yc').on('click', function () {
            var yxan = Ext.getCmp('panel-1147');
            if (yxan.isVisible()) {
                yxan.hide();
            } else { yxan.show(); }
        });




    })




    if (otype == $Otype.ADD) {
        mstform.getItem('yf').addListener('change', function () {

            var b = mstform.getItem('yf').getValue();
            var a = mstform.getItem('nd').getValue();
            if (b) {
                var pc = mstform.getItem('ocode').getValue()
                callServer('pc', [{ 'pc': pc }],
                    function (res) {
                        if (res) {
                            mstform.getItem('title').setValue(res.record[0].oname + '人员2025年' + b + '月工资表');
                        }
                    });
            }
            if (a && b) {
                var firstDay = new Date(a, +b - 1, 1);
                var nextMonthFirstDay = new Date(a, +b, 1);
                var lastDay = new Date(nextMonthFirstDay - 1);
                mstform.getItem('datetimecol_1').setValue(firstDay);
                mstform.getItem('datetimecol_2').setValue(lastDay);
            }
        });

        mstform.getItem('nd').addListener('change', function () {

            var b = mstform.getItem('yf').getValue();
            var a = mstform.getItem('nd').getValue();
            if (b) {
                var pc = mstform.getItem('ocode').getValue()
                callServer('pc', [{ 'pc': pc }],
                    function (res) {
                        if (res) {
                            mstform.getItem('title').setValue(res.record[0].oname + '人员2025年' + b + '月工资表');
                        }
                    });
            }
            if (a && b) {
                var firstDay = new Date(a, +b - 1, 1);
                var nextMonthFirstDay = new Date(a, +b, 1);
                var lastDay = new Date(nextMonthFirstDay - 1);
                mstform.getItem('datetimecol_1').setValue(firstDay);
                mstform.getItem('datetimecol_2').setValue(lastDay);
            }
        });
    }





    mstform.getItem('empidmul').addListener('helpselected', async function () {
        var intArray = mstform.getItem('empidmul').getValue();
        var date = mstform.getItem('datetimecol_2').getValue();
        var array = intArray.split(",");

        // 将 callServer 封装为 Promise
        function callServerPromise(service, params) {
            return new Promise((resolve) => {
                callServer(service, params, function (res) {
                    resolve(res);
                });
            });
        }

        // 使用 async/await 确保顺序执行
        for (let i = 0; i < array.length; i++) {
            var hr_phid = array[i];

            // 第一个 callServer 调用
            var res1 = await callServerPromise('ryxx', [{ 'phid': hr_phid }]);
            if (res1.record.length > 0) {
                var arr2 = [];
                for (let j = 0; j < res1.record.length; j++) {
                    arr2.push({
                        empid: res1.record[j].phid,
                        empid_name: res1.record[j].cname,
                        textcol_1: res1.record[j].cardno,
                        datetimecol_1: res1.record[j].cdt
                    });
                }
                dstore.insert(dstore.getCount(), arr2);
            }
        }

        mstform.getItem('empidmul').setValue('');
    });

    mstform.getItem('userhelp_char_1').on('beforetriggerclick', function (eOp, ignoreBeforeEvent) {
        var a = mstform.getItem('ocode').getValue();
        mstform.getItem('userhelp_char_1').setClientSqlFilter('ocode = ' + a);              /*PC对应通用帮助拼接SQL语句条件过滤 
                                                                                                          *arr的用法可能不对,这里是SQL语句的拼接 arr数组无法In识别*/
    });


mstform.getItem('userhelp_char_1').addListener('helpselected', async function () {
    try {
        // 显示等待提示
        Ext.Msg.wait("正在处理数据...", "请稍候");

        var nd = mstform.getItem('nd').getValue();
        var yf = mstform.getItem('yf').getValue();
        var pc = mstform.getItem('ocode').getValue();

        // 验证输入
        if (Ext.isEmpty(nd)) {
            Ext.Msg.hide();
            Ext.Msg.alert('提示', '请先选择年度!');
            return false;
        }
        if (Ext.isEmpty(Ext.getCmp('yf').getValue())) {
            Ext.Msg.hide();
            Ext.Msg.alert('提示', '请先输入月份!');
            return false;
        }

        var intArray = mstform.getItem('userhelp_char_1').getValue();
        var date = mstform.getItem('datetimecol_2').getValue();

        // 将 callServer 封装为 Promise
        function callServerPromise(service, params) {
            return new Promise((resolve) => {
                callServer(service, params, function (res) {
                    resolve(res);
                });
            });
        }

        // 获取 fxry 数据
        var fxryRes = await callServerPromise('fxry', [{ 'phid': intArray }]);

        // 定义分批处理参数
        const batchSize = 5; // 每批处理5条记录
        let currentIndex = 0;
        let missingRecords = []; // 存储没有记录的人员
        let existingRecords = new Set(); // 存储已存在的记录phid,用于去重

        // 预先收集已存在的数据的phid
        dstore.each(function (record) {
            existingRecords.add(record.get('empid') + record.get('deptid'));
        });
        
        dstore1.each(function (record) {
            existingRecords.add(record.get('empid') + record.get('deptid'));
        });

        // 分批处理函数
        async function processBatch() {
            const endIndex = Math.min(currentIndex + batchSize, fxryRes.record.length);

            // 处理当前批次
            for (let i = currentIndex; i < endIndex; i++) {
                var hr_phid = fxryRes.record[i].empid;
                var hr_name = fxryRes.record[i].empid_name;
                var ddlbcol_1 = fxryRes.record[i].ddlbcol_1;

                // 获取 ryxx 数据
                var ryxxRes = await callServerPromise('ryxx', [{ 'phid': hr_phid, 'nd': nd, 'yf': yf }]);

                if (ryxxRes.record.length > 0) {
                    var arr2 = [];
                    for (let j = 0; j < ryxxRes.record.length; j++) {
                        // 检查是否已存在
                        if (!existingRecords.has(ryxxRes.record[j].phid + ryxxRes.record[j].dept)) {
                            // 根据ddlbcol_1决定使用哪个数据集的字段映射
                            const fieldMap = getFieldMapping(ddlbcol_1 == 0 ? 'main' : 'secondary');
                            
                            // 创建基础记录对象
                            let recordData = {
                                [fieldMap.empid]: ryxxRes.record[j].phid,
                                [fieldMap.empid_name]: ryxxRes.record[j].cname,
                                [fieldMap.sfz]: ryxxRes.record[j].cardno,
                                [fieldMap.rzrq]: ryxxRes.record[j].cdt,
                                [fieldMap.zz]: ryxxRes.record[j].cboo,
                                [fieldMap.zz_name]: ryxxRes.record[j].cbooname,
                                [fieldMap.deptid]: ryxxRes.record[j].dept,
                                [fieldMap.deptid_name]: ryxxRes.record[j].dpname,
                                [fieldMap.gw]: ryxxRes.record[j].gw,
                                [fieldMap.checkboxcol_2]: 1,
                                [fieldMap.numericcol_3]: 1.0,
                                [fieldMap.status]: ryxxRes.record[j].ygzt,
                                [fieldMap.textcol_2]: ryxxRes.record[j].yhkh,
                            };
                            
                            // 根据ddlbcol_1添加不同的userhelp_1字段
                            if (ddlbcol_1 == 0) {
                                recordData[fieldMap.userhelp_1] = ryxxRes.record[j].dept;
                                recordData[fieldMap.userhelp_1_name] = ryxxRes.record[j].dpname;
                            } else if (ddlbcol_1 == 1) {
                                var xmxx = await callServerPromise('xmxx', [{ 'phid': ryxxRes.record[j].dept }]);
                                if (xmxx.record.length > 0) {
                                    recordData[fieldMap.userhelp_1] = xmxx.record[0].user_glxm;
                                    recordData[fieldMap.userhelp_1_name] = xmxx.record[0].project_Name;
                                }
                            }
                            
                            arr2.push(recordData);
                            existingRecords.add(ryxxRes.record[j].phid + ryxxRes.record[j].dept);
                        }
                    }

                    // 插入数据到对应的store
                    if (arr2.length > 0) {
                        if (ddlbcol_1 == 0) {
                            dstore.insert(dstore.getCount(), arr2);
                        } else if (ddlbcol_1 == 1) {
                            dstore1.insert(dstore1.getCount(), arr2);
                        }
                    }

                    // 每处理完一条就让UI有机会更新
                    await new Promise(resolve => setTimeout(resolve, 0));
                } else {
                    // 记录没有数据的人员
                    missingRecords.push(hr_name);
                }
            }

            currentIndex = endIndex;

            // 如果还有数据,继续下一批
            if (currentIndex < fxryRes.record.length) {
                setTimeout(processBatch, 0);
            } else {
                // 全部处理完成
                mstform.getItem('empidmul').setValue('');
                Ext.Msg.hide();
                dgrid.getView().refresh(); // 刷新视图
                if (dgrid1) dgrid1.getView().refresh(); // 刷新第二个网格视图

                // 如果有缺失记录,显示提示
                if (missingRecords.length > 0) {
                    Ext.Msg.show({
                        title: '提示',
                        msg: '以下人员没有提考勤:<br>' + missingRecords.join('<br>'),
                        width: 400,
                        buttons: Ext.Msg.OK,
                        icon: Ext.Msg.WARNING
                    });
                }
            }
        }

        // 开始处理
        await processBatch();

    } catch (error) {
        Ext.Msg.hide();
        Ext.Msg.alert('提示', '请检查没有出现组织和部门的员工企业员工库任职信息是否勾选发薪');
        console.error('处理过程中发生错误:', error);
    }
});



    dgrid.addListener('beforeedit', function (editor, e) {
        // 在编辑开始前拦截
        if (e.field == 'gzbz') {
            var a;
            var record = e.record;

            // 定义不允许修改的empid数组
            var excludedEmpIds = [
                '306200221000013',
                '306200221000003',
                '537200326001079',
                '537200326000202',
                '614000000001441',
                '806210322000007',
                '806210510000009',
                '614000000001772'
            ];

            callServer('yglxbz', [{ 'phid': record.get('empid') }], function (res) {
                if (res) {
                    a = res.record[0].emptype;
                }
            });

            if (record.get('u_ygzt') == '正式'
                && !excludedEmpIds.includes(record.get('empid'))
                && a != '806210410000001') {
                Ext.Msg.alert('提示', '正式员工不允许修改薪资!');
                return false; // 完全阻止进入编辑模式
            }
        }
        return true;
    });

}

function timestampToTime(timestamp) {

    var date = new Date(timestamp);
    var y = date.getFullYear();
    var m = date.getMonth() + 1;
    m = m < 10 ? ('0' + m) : m;
    var d = date.getDate();
    d = d < 10 ? ('0' + d) : d;
    var h = date.getHours();
    var minute = date.getMinutes();
    minute = minute < 10 ? ('0' + minute) : minute;
    return y + '-' + m + '-' + d  //这里如果不需要小时 分  后边的可以不需要拼接

}


function getDaysLeftInMonth(dateStr) {
    var date = new Date(dateStr);
    var currentMonth = date.getMonth();
    var currentYear = date.getFullYear();
    var nextMonthFirstDay = new Date(currentYear, currentMonth + 1, 1);
    var currentDay = date.getDate();
    var daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate(); // 获取当前月的总天数
    var daysLeft = daysInMonth - currentDay;
    return daysLeft;
}

function getDaysIncludingGivenDate(dateStr) {
    // 创建一个 Date 对象
    var date = new Date(dateStr);

    // 获取当前日期在这个月中的天数
    var currentDay = date.getDate();

    // 计算当月中包括给定日期在内的天数
    var daysIncluding = currentDay;

    return daysIncluding;
}

function getDaysInMonth(dateStr) {
    // 创建一个 Date 对象
    const date = new Date(dateStr);

    // 获取当前日期所在的年份和月份
    const year = date.getFullYear();
    const month = date.getMonth();

    // 创建一个表示下个月第一天的 Date 对象,然后将日期设置为 0
    // 这样 getDate() 方法就会返回当前月份的总天数
    const daysInMonth = new Date(year, month + 1, 0).getDate();

    return daysInMonth;
}




/**
 * 计算给定日期所在月份的周末和节假日天数(支持节假日区间)
 * @param {Date|string} date - 基准日期
 * @param {Array} holidayRanges - 节假日区间数组,格式如 [{ start: 'YYYY-MM-DD', end: 'YYYY-MM-DD' }]
 * @param {string} [range="all"] - 计算范围: "before"(之前)、"after"(之后)、"all"(全部)
 * @returns {number} 符合条件的周末和节假日天数
 */
function countMonthSpecialDays(date, holidayRanges = [], workWeekends = [], range = "all", endDateParam = null) {
    // 处理输入日期
    const inputDate = typeof date === 'string' ? new Date(date) : new Date(date);
    if (isNaN(inputDate.getTime())) {
        throw new Error('Invalid date input');
    }

    // 确定开始和结束日期
    let firstDay, lastDay;
    if (endDateParam) {
        // 如果有结束日期参数,则计算两个日期之间的范围
        firstDay = new Date(inputDate);
        lastDay = typeof endDateParam === 'string' ? new Date(endDateParam) : new Date(endDateParam);
        if (isNaN(lastDay.getTime())) {
            throw new Error('Invalid end date input');
        }
        // 确保开始日期不大于结束日期
        if (firstDay > lastDay) {
            throw new Error('Start date must be before or equal to end date');
        }
    } else {
        // 如果没有结束日期参数,则计算整个月份
        const year = inputDate.getFullYear();
        const month = inputDate.getMonth();
        firstDay = new Date(year, month, 1);
        lastDay = new Date(year, month + 1, 0);
    }

    const currentDay = inputDate.getDate();
    let count = 0;

    // 遍历日期范围
    for (let day = new Date(firstDay); day <= lastDay; day.setDate(day.getDate() + 1)) {
        const dayOfMonth = day.getDate();
        const dayOfWeek = day.getDay(); // 0=周日, 6=周六
        const formattedDate = formatDate(day); // 'YYYY-MM-DD'

        // 检查是否在计算范围内
        let isInRange = false;
        if (range === "before" && dayOfMonth < currentDay) {
            isInRange = true;
        } else if (range === "after" && dayOfMonth >= currentDay) {
            isInRange = true;
        } else if (range === "all") {
            isInRange = true;
        }

        if (isInRange) {
            // 检查是否是调休工作日(周末需要上班)
            const isWorkWeekend = workWeekends.includes(formattedDate);

            // 计算周末(跳过调休日)
            if (!isWorkWeekend) {
                const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
                const isHoliday = isDateInHolidayRanges(day, holidayRanges);

                if (isHoliday) {
                    count += 1; // 节假日统一算1天
                } else if (isWeekend) {
                    if (dayOfWeek === 0) {
                        count += 1; // 周日算1天
                    } else if (dayOfWeek === 6) {
                        count += 0.5; // 周六算0.5天
                    }
                }
            }
        }
    }

    return count;
}

// 辅助函数:检查某一天是否在节假日区间内
function isDateInHolidayRanges(date, holidayRanges) {
    const checkDate = new Date(date);
    for (const range of holidayRanges) {
        const startDate = new Date(range.start);
        const endDate = new Date(range.end);
        if (checkDate >= startDate && checkDate <= endDate) {
            return true;
        }
    }
    return false;
}

// 辅助函数:格式化日期为 'YYYY-MM-DD'
function formatDate(date) {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    return `${year}-${month}-${day}`;
}

// 简化的字段映射函数
function getFieldMapping(datasetName) {
    if (datasetName === 'main') {
        return {
            // 主数据集字段映射
            checkboxcol_2: 'checkboxcol_2',//选择
            zz: 'zz',//组织
            zz_name: 'zz_name',//组织
            deptid: 'deptid',//部门
            empid: 'empid',//人员
            deptid_name: 'deptid_name',//部门
            empid_name: 'empid_name',//人员
            sfz: 'textcol_1',//身份证号码
            rzrq:'datetimecol_1',   //入职日期
            status: 'u_ygzt',    //员工状态   
            gw:'gw',//岗位
            gzbz:'gzbz',//工资标准
            jxts: 'jxts',//计薪天数
            byts: 'byts',//出勤天数
            numericcol_4: 'numericcol_4',//额外请假天数
            numericcol_3: 'numericcol_3',//系数
            jxbl: 'u_jxbl',//绩效比例
            xlbz: 'xlbz',//餐饮补助
            u_dnbz: 'u_dnbz',//u_dnbz
            zcbz: 'zcbz',//	职称补助
            zwbz: 'zwbz',//	驻外补助
            qtbz: 'qtbz',//其他补助
            bzhj:'bzhj',//   补助合计
            jj: 'jj',   //奖金    
            qjkk:'qjkk',//其他扣款
            yfhj: 'yfhj',//应发合计
            yldw: 'yldw',//养老单位
            ylgr: 'ylgr',//养老个人
            yldw1: 'yldw1',//医疗单位
            ylgr1: 'ylgr1',//医疗个人
            sydw: 'sydw',//失业单位
            sygr: 'sygr',//失业个人
            sydw1: 'sydw1',//生育单位
            gsdw: 'gsdw',//工伤单位
            dedw: 'dedw',//大额单位
            degr: 'degr',//大额个人
            dwhj: 'dwhj',//单位合计
            grhj: 'grhj',//个人合计
            gjjdw:'gjjdw',  // 公积金单位
            gjjgr: 'gjjgr',   //公积金个人    
            ynshj:'ynshj',//除专项附加扣除外应纳税工资合计
            u_grsdr: 'u_grsdr',//个人所得税
            u_jxgskk: 'u_jxgskk',//绩效工资扣款
            numericcol_5: 'numericcol_5',//绩效补充扣款
            numericcol_2: 'numericcol_2',//工会会员会费
            u_sfhj: 'u_sfhj',//实发合计
            numericcol_1:'numericcol_1',//实际出勤天数
            textcol_2:'textcol_2'//银行卡号
        };
    } else {
        return {
            // 第二个数据集字段映射  
            checkboxcol_2: 'u_xzk',//选择
            zz: 'u_zz',//组织
            zz_name: 'u_zz_name',//组织
            deptid: 'deptid',//部门
            deptid_name: 'deptid_name',//部门
            empid: 'empid',//人员
            empid_name: 'empid_name',//人员
            sfz: 'textcol_1',//身份证号码
            rzrq:'datetimecol_1',   //入职日期
            status: 'u_ygzt',    //员工状态   
            gw:'u_gw',//岗位
            gzbz:'u_gzbz',//工资标准
            jxts: 'u_jxts',//计薪天数
            byts: 'u_byts',//出勤天数
            numericcol_4: 'numericcol_37',//额外请假天数
            numericcol_3: 'numericcol_39',//系数
            jxbl: 'u_jxbl',//绩效比例
            xlbz: 'u_cybz',//餐饮补助
            u_dnbz: 'u_dnbz',//电脑补助
            zcbz: 'u_zcbz',//	职称补助
            zwbz: 'u_zwbz',//	驻外补助
            qtbz: 'u_qtbz',//其他补助
            bzhj:'u_bzhj',//   补助合计
            jj: 'u_jj',   //奖金    
            qjkk:'u_qjkk',//其他扣款
            yfhj: 'u_yfhj',//应发合计
            yldw: 'u_yldw',//养老单位
            ylgr: 'u_ylgr',//养老个人
            yldw1: 'u_yldw1',//医疗单位
            ylgr1: 'u_ylgr1',//医疗个人
            sydw: 'u_sydw',//失业单位
            sygr: 'u_sygr',//失业个人
            sydw1: 'u_sydw1',//生育单位
            gsdw: 'u_gsdw',//工伤单位
            dedw: 'u_dedw',//大额单位
            degr: 'u_degr',//大额个人
            dwhj: 'u_dwhj',//单位合计
            grhj: 'u_grhj',//个人合计
            gjjdw:'u_gjjdw',  // 公积金单位
            gjjgr: 'u_gjjgr',   //公积金个人    
            ynshj:'u_ynshj',//除专项附加扣除外应纳税工资合计
            u_grsdr: 'u_grsdr',//个人所得税
            u_jxgskk: 'u_jxgskk',//绩效工资扣款
            numericcol_2: 'u_ghhyhf',//工会会员会费
            u_sfhj: 'u_sfhj',//实发合计
            numericcol_1:'numericcol_38',//实际出勤天数
            textcol_2:'textcol_4'//银行卡号
        };
    }
}
console 命令行工具 X clear

                    
>
console