Explorar el Código

报销功能调整(添加数电发票拖拽排序,添加孔璐全部确认功能)

徐滕 hace 1 mes
padre
commit
89573b5389

+ 16 - 0
src/main/java/com/jeeplus/modules/workprojectnotify/web/WorkProjectNotifyController.java

@@ -8,6 +8,8 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.collect.Lists;
 import com.google.gson.Gson;
 import com.jeeplus.common.config.Global;
@@ -10691,6 +10693,7 @@ public class WorkProjectNotifyController extends BaseController {
 					));
 			//获取专业类型
 			List<MainDictDetail> certificateMajor = DictUtils.getMainDictList("invoiceReimbursementType");
+			List<String> reimbursementElectronicInvoiceVATTaxeIdList = Lists.newArrayList();
 			for (ReimbursementVATTax vatTax : workReimbursement.getReimbursementElectronicInvoiceVATTaxes()) {
 				//判断状态
 				String status = statusMap.get(vatTax.getId());
@@ -10705,7 +10708,20 @@ public class WorkProjectNotifyController extends BaseController {
 						vatTax.setInvoiceTypeStr(dictDetail.getLabel());
 					}
 				}
+				reimbursementElectronicInvoiceVATTaxeIdList.add(vatTax.getId());
 			}
+
+			// 2. 转换为JSON格式字符串(关键:用工具类生成标准JSON)
+			String vatTaxIdsJson;
+			try {
+				// 使用Jackson的ObjectMapper
+				ObjectMapper objectMapper = new ObjectMapper();
+				vatTaxIdsJson = objectMapper.writeValueAsString(reimbursementElectronicInvoiceVATTaxeIdList);
+			} catch (JsonProcessingException e) {
+				// 异常处理(如转换失败,返回空数组)
+				vatTaxIdsJson = "[]";
+			}
+			model.addAttribute("reimbursementElectronicInvoiceVATTaxeIdList",vatTaxIdsJson);
 		}
 
 		String returnPath = "modules/workreimbursement/";

+ 10 - 6
src/main/resources/mappings/modules/workreimbursement/ReimbursementVATTaxDao.xml

@@ -22,7 +22,8 @@
 		a.reimbursement_type AS "reimbursementType",
 		a.invoice_project_name AS "invoiceProjectName",
 		a.remarks AS "remarks",
-		a.parent_id AS "parentId"
+		a.parent_id AS "parentId",
+		a.index_number as "indexNumber"
 	</sql>
 	
 	<sql id="ReimbursementVATTaxJoins">
@@ -53,7 +54,7 @@
 				ORDER BY ${page.orderBy}
 			</when>
 			<otherwise>
-				ORDER BY a.create_date ASC
+				ORDER BY a.index_number ASC
 			</otherwise>
 		</choose>
 	</select>
@@ -71,7 +72,7 @@
 				ORDER BY ${page.orderBy}
 			</when>
 			<otherwise>
-				ORDER BY a.create_date ASC
+				ORDER BY a.index_number ASC
 			</otherwise>
 		</choose>
 	</select>
@@ -96,7 +97,8 @@
 			invoice_unit,
 			reimbursement_type,
 			invoice_project_name,
-			parent_id
+			parent_id,
+			index_number
 		) VALUES (
 			#{id},
 			#{invoiceCode},
@@ -116,7 +118,8 @@
 			#{invoiceUnit},
 			#{reimbursementType},
 			#{invoiceProjectName},
-			#{parentId}
+			#{parentId},
+			#{indexNumber}
 		)
 	</insert>
 	
@@ -136,7 +139,8 @@
 			invoice_unit = #{invoiceUnit},
 			reimbursement_type = #{reimbursementType},
 			invoice_project_name = #{invoiceProjectName},
-			parent_id = #{parentId}
+			parent_id = #{parentId},
+			index_number = #{indexNumber}
 		WHERE id = #{id}
 	</update>
 	

+ 189 - 33
src/main/webapp/webpage/modules/workreimbursement/treeForm/all/workReimbursementAllFormAdd.jsp

@@ -102,6 +102,14 @@
             });
             // getRandom();
 
+
+            // 初始化现有tbody
+            initExistingTbodys();
+            // 监听动态生成的tbody
+            setupDOMObserver();
+            // 覆盖上传回调
+            overrideUploadCallback();
+
             laydate.render({
                 elem: '#invoiceDate', //目标元素。由于laydate.js封装了一个轻量级的选择器引擎,因此elem还允许你传入class、tag但必须按照这种方式 '#id .class'
                 event: 'focus', //响应事件。如果没有传入event,则按照默认的click
@@ -309,9 +317,6 @@
                                     "</table>" +
                                     "</td></tr>")
 
-
-
-                                console.log("parentIndex",index)
                                 $.ajax({
                                     type : "POST",
                                     url:"${ctx}/workReimbursementNew/workReimbursementNew/formByAccount",
@@ -353,6 +358,185 @@
 
 
 
+
+        // 初始化页面已存在的tbody
+        function initExistingTbodys() {
+            $('tbody[id^="workAccountList_"]:not(.sortable-initialized)').each(function() {
+                initTbodySortable($(this));
+            });
+        }
+
+        // 监听DOM变化
+        function setupDOMObserver() {
+            const tableContainer = document.getElementById('contentTable');
+            if (!tableContainer) return;
+
+            const observer = new MutationObserver(function(mutations) {
+                mutations.forEach(function(mutation) {
+                    $(mutation.addedNodes).find('tbody[id^="workAccountList_"]:not(.sortable-initialized)')
+                        .each(function() {
+                            setTimeout(() => {
+                                initTbodySortable($(this));
+                            }, 200);
+                        });
+                });
+            });
+
+            observer.observe(tableContainer, {
+                childList: true,
+                subtree: true
+            });
+        }
+
+        // 覆盖上传回调
+        function overrideUploadCallback() {
+            const originalUploadFunc = window.newInsertTitleInvoiceReimbursement;
+            if (originalUploadFunc) {
+                window.newInsertTitleInvoiceReimbursement = function(rowId, fileInput) {
+                    originalUploadFunc(rowId, fileInput);
+                    setTimeout(() => {
+                        const $newTbody = $(`#${rowId}`).closest('table').find('tbody[id^="workAccountList_"]:not(.sortable-initialized)');
+                        if ($newTbody.length) {
+                            initTbodySortable($newTbody);
+                        }
+                    }, 500);
+                };
+            }
+        }
+
+        // 初始化单个tbody的拖拽
+        function initTbodySortable($tbody) {
+            if ($tbody.hasClass('sortable-initialized')) return;
+            $tbody.addClass('sortable-initialized');
+
+            // 用自定义数据属性标记是否正在拖拽(替代instance方法)
+            $tbody.data('isSorting', false);
+
+            $tbody.sortable({
+                items: 'tr:not(.summary-row)',
+                helper: fixHelperModified,
+                stop: function() {
+                    updateIndependentIndex($tbody);
+                    // 拖拽结束,标记为false
+                    $tbody.data('isSorting', false);
+                },
+                update: function() {
+                    syncSortOrder($tbody);
+                },
+                containment: $tbody,
+                appendTo: 'body',
+                zIndex: 10000,
+                cancel: '',
+                handle: '',
+                start: function() {
+                    console.log('拖拽开始');
+                    // 拖拽开始,标记为true
+                    $tbody.data('isSorting', true);
+                }
+            }).disableSelection();
+
+            // 处理只读input的点击事件(用自定义数据属性判断)
+            $tbody.find('input[readonly]').on('mousedown', function(e) {
+                if (e.which !== 1) return; // 只处理左键
+
+                const $tr = $(this).closest('tr:not(.summary-row)');
+                if ($tr.length && !$tbody.data('isSorting')) { // 这里替换instance判断
+                    // 手动触发tr的mousedown,模拟拖拽
+                    $tr.trigger('mousedown', [e]);
+                }
+            });
+        }
+
+        // 保持拖拽时单元格宽度
+        function fixHelperModified(e, tr) {
+            const $originals = tr.children();
+            const $helper = tr.clone();
+            $helper.children().each(function(index) {
+                $(this).width($originals.eq(index).width());
+            });
+            return $helper;
+        }
+
+        // 核心优化:每个tbody独立计算序号(从1开始)
+        function updateIndependentIndex($currentTbody) {
+            // 强制确认当前tbody是否有效
+            if (!$currentTbody || !$currentTbody.length) {
+                console.error("错误:未找到有效的tbody元素");
+                return;
+            }
+
+            // 获取tbody的id(兜底处理)
+            const tbodyId = $currentTbody.attr('id') || "匿名tbody";
+
+            // 遍历可拖拽行
+            const $rows = $currentTbody.find('tr:not(.summary-row)');
+            if (!$rows.length) {
+                console.log("[Input统计] tbody[" + tbodyId + "] 内没有可拖拽的行");
+                return;
+            }
+
+            $rows.each(function(rowIndex) {
+                const rowNum = rowIndex + 1;
+                if (isNaN(rowNum)) {
+                    console.warn("[警告] tbody[" + tbodyId + "] 行索引异常:" + rowIndex);
+                    return;
+                }
+
+                const newIndex = rowIndex; // 根据需求调整是否+1
+
+                // 1. 更新序号td
+                const $indexTd = $(this).find('td').eq(2);
+                if ($indexTd.length) {
+                    $indexTd.text(newIndex);
+                } else {
+                    console.warn("[警告] tbody[" + tbodyId + "] 第" + rowNum + "行未找到第三个td");
+                }
+
+                // 2. 处理第一个td中的input
+                const $firstTd = $(this).find('td').eq(0);
+                if (!$firstTd.length) {
+                    console.warn("[警告] tbody[" + tbodyId + "] 第" + rowNum + "行未找到第一个td");
+                    return;
+                }
+
+                const $allInputsInTd = $firstTd.find('input');
+                const totalInputs = $allInputsInTd.length;
+
+
+                const targetInputIndex = 14; // 第15个input(0开始)
+                if (totalInputs > targetInputIndex) {
+                    const $targetInput = $allInputsInTd.eq(targetInputIndex);
+                    $targetInput.val(newIndex);
+                }
+            });
+        }
+
+
+        // 同步排序数据
+        function syncSortOrder($tbody) {
+            $tbody.find('tr:not(.summary-row)').each(function(index) {
+                const sortIndex = index;
+                const $row = $(this);
+
+                const $idInput = $row.find('input[name*="reimbursementElectronicInvoiceVATTaxes"][name*=".id"]');
+                if ($idInput.length) {
+                    const idName = $idInput.attr('name');
+                    const sortName = idName.replace('.id', '.sort');
+                    let $sortInput = $row.find(`input[name="${sortName}"]`);
+
+                    if ($sortInput.length) {
+                        $sortInput.val(sortIndex);
+                    } else {
+                        $row.find('td:first').append(`
+                    <input type="hidden" name="${sortName}" value="${sortIndex}">
+                `);
+                    }
+                }
+            });
+        }
+
+
+
         /**
          * 插入行数据
          * @param tbodyId
@@ -392,6 +576,7 @@
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_fileSize' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].fileSize' type='hidden' value='" + data.fileSize +"'/>"+
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_divIdType' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].divIdType' type='hidden' value='" + data.divIdType +"'/>" +
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_parentId' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].parentId' type='hidden' value='" + data.parentId + "'/>" +
+                "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_indexNumber' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].indexNumber' type='hidden' value='" + data.indexNumber + "'/>" +
                 "</td>"+
 
                 <%--序号--%>
@@ -510,7 +695,6 @@
                             "reimbursementId": $("#wId").val()
                         },
                         success:function(data){
-                            console.log(data)
                             if(!data.success){
                                 decideFlag = true
                                 parent.layer.msg(data.message, {icon: 5});
@@ -918,6 +1102,7 @@
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_fileSize' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].fileSize' type='hidden' value=''/>"+
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_divIdType' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].divIdType' type='hidden' value=''/>" +
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_parentId' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].parentId' type='hidden' value='" + tbodyId + "'/>" +
+                "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_indexNumber' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].indexNumber' type='hidden' value=''/>" +
                 "</td>"+
 
                 <%--序号--%>
@@ -1145,8 +1330,6 @@
 
         // 处理文件上传
         async function handleFileNewUpload(file, size, trlen,inputId,parentIndex) {
-            console.log("inputId",inputId)
-            console.log("parentIndex",parentIndex)
 
             const $tbody = $(inputId);
 
@@ -1385,10 +1568,6 @@
 
         // 数电发票删除 - 隐藏行版本(保留DOM,只隐藏)
         function delRowNew(obj, prefix, parentIndex) {
-            console.log("===== 开始执行delRowNew函数 =====");
-            console.log("当前删除按钮元素:", obj);
-            console.log("prefix参数:", prefix);
-            console.log("parentIndex参数:", parentIndex);
 
             // 获取相关元素
             var $idInput = $(prefix + "_id");
@@ -1401,39 +1580,32 @@
             var $targetInput = $currentRow.find("td:first-child input:eq(1)");
             if ($targetInput.length > 0) {
                 $targetInput.val("1");
-                console.log("已将删除标记设为1");
             }
 
             // 隐藏当前行
             $currentRow.addClass("hidden");
-            console.log("已隐藏当前行");
 
             // 处理父表格显示状态(根据可见行数量)
             if ($parentTable.length > 0) {
                 // 筛选非空且未隐藏的行
                 var visibleRows = $parentTable.find("tr:not(:empty):not(.hidden)");
-                console.log("父表格可见行数:", visibleRows.length);
 
                 // 控制表格显示/隐藏
                 if (visibleRows.length === 0) {
                     $parentTable.hide();
-                    console.log("父表格已隐藏(无可见行)");
                 } else {
                     $parentTable.show();
-                    console.log("父表格已显示");
                 }
 
                 // 隐藏关联行(如果有idValue)
                 if (idValue) {
                     var targetTrClass = idValue;
                     $parentTable.find("tr." + targetTrClass).addClass("hidden");
-                    console.log("已隐藏关联行(class: " + targetTrClass + ")");
                 }
             }
 
             // 重新排序行号
             reorderRowNumbers($parentTable);
-            console.log("已重新排序行号");
 
             // 查找当前行所在的tbody并获取其id
             const td = obj.closest('td');
@@ -1444,24 +1616,20 @@
             //对数据进行重新处理
             updateSummaryRow("#" + tbodyId)
 
-            console.log("查找的tbodyId:", tbodyId);
             if (!tbodyId) {
                 console.error("未找到有效的tbody,终止金额汇总");
                 return;
             }
 
             // 汇总金额和有效行数(核心修复:选择器添加#前缀)
-            console.log("开始汇总金额,目标tbody选择器: #", tbodyId);
             var total = 0;
             var validRowCount = 0;
 
             // 修复选择器:通过# + tbodyId定位元素
             $("#" + tbodyId).find('tr').each(function(index, tr) {
-                console.log("正在处理第", index + 1, "行");
 
                 // 验证行是否可见(非隐藏)
                 if ($(tr).hasClass("hidden")) {
-                    console.log("第", index + 1, "行是隐藏行,跳过");
                     return true; // 继续下一行
                 }
 
@@ -1469,16 +1637,13 @@
                 var $firstTd = $(tr).find('td').eq(0);
                 var $secondInput = $firstTd.find('input').eq(1);
                 var secondInputValue = $secondInput.val() || '';
-                console.log("第", index + 1, "行的删除标记值:", secondInputValue.trim());
 
                 if (secondInputValue.trim() !== '0') {
-                    console.log("第", index + 1, "行不符合条件,跳过");
                     return true; // 继续下一行
                 }
 
                 // 累加有效行数
                 validRowCount++;
-                console.log("第", index + 1, "行有效,累计有效行数:", validRowCount);
 
                 // 汇总第八个td中第一个input的值
                 var $eighthTd = $(tr).find('td').eq(8);
@@ -1487,12 +1652,10 @@
                 var num = parseFloat(value);
                 var addAmount = isNaN(num) ? 0 : num;
                 total += addAmount;
-                console.log("第", index + 1, "行金额:", addAmount, "当前累计总金额:", total);
             });
 
             // 处理汇总结果(保留两位小数)
             total = total.toFixed(2) * 1;
-            console.log("最终汇总金额:", total, "有效行数:", validRowCount);
 
             // 更新数电发票金额和数量输入框
             var $eInvoiceMoney = $("#workAccountList" + parentIndex + "_eInvoiceMoney");
@@ -1500,15 +1663,11 @@
 
             $eInvoiceMoney.val(total);
             $eInvoiceBills.val(validRowCount);
-            console.log("已更新金额输入框:", $eInvoiceMoney.val(), "数量输入框:", $eInvoiceBills.val());
 
             // 调用汇总方法(修复变量重复声明问题)
             var sumResult = calculateSum(parentIndex);
             var billResult = billSum(parentIndex);
-            console.log("calculateSum结果:", sumResult);
-            console.log("billSum结果:", billResult);
 
-            console.log("===== delRowNew函数执行结束 =====");
         }
 
         // 重新排序行号的函数(只处理未隐藏的行,行号在第二个td中)
@@ -2564,7 +2723,6 @@
             }
 
             var idc = $("#workAccountList" + rowIndex + "_id").val();
-            console.log("idc", idc);
 
             // 1. 校验idc有效性,避免查找无效元素
             if (!idc || idc.trim() === "") {
@@ -2618,7 +2776,6 @@
                 }
             });
 
-            console.log('数电票可报销的最大额度:', maxMoney.toFixed(2));
 
 
             // 4. 计算当前行的金额(单行汇总)
@@ -2641,7 +2798,6 @@
             totalAllInvoice += invoice;
             totalAllSum += rowSum;
 
-            console.log("计算汇总金额",eInvoice)
         });
 
         // 7. 重新计算总报销费用(传入所有行的非数电票总金额)

+ 189 - 32
src/main/webapp/webpage/modules/workreimbursement/treeForm/all/workReimbursementAllModifyApply.jsp

@@ -102,6 +102,14 @@
             });
             // getRandom();
 
+
+            // 初始化现有tbody
+            initExistingTbodys();
+            // 监听动态生成的tbody
+            setupDOMObserver();
+            // 覆盖上传回调
+            overrideUploadCallback();
+
             laydate.render({
                 elem: '#invoiceDate', //目标元素。由于laydate.js封装了一个轻量级的选择器引擎,因此elem还允许你传入class、tag但必须按照这种方式 '#id .class'
                 event: 'focus', //响应事件。如果没有传入event,则按照默认的click
@@ -377,6 +385,185 @@
 
 
 
+
+        // 初始化页面已存在的tbody
+        function initExistingTbodys() {
+            $('tbody[id^="workAccountList_"]:not(.sortable-initialized)').each(function() {
+                initTbodySortable($(this));
+            });
+        }
+
+        // 监听DOM变化
+        function setupDOMObserver() {
+            const tableContainer = document.getElementById('contentTable');
+            if (!tableContainer) return;
+
+            const observer = new MutationObserver(function(mutations) {
+                mutations.forEach(function(mutation) {
+                    $(mutation.addedNodes).find('tbody[id^="workAccountList_"]:not(.sortable-initialized)')
+                        .each(function() {
+                            setTimeout(() => {
+                                initTbodySortable($(this));
+                            }, 200);
+                        });
+                });
+            });
+
+            observer.observe(tableContainer, {
+                childList: true,
+                subtree: true
+            });
+        }
+
+        // 覆盖上传回调
+        function overrideUploadCallback() {
+            const originalUploadFunc = window.newInsertTitleInvoiceReimbursement;
+            if (originalUploadFunc) {
+                window.newInsertTitleInvoiceReimbursement = function(rowId, fileInput) {
+                    originalUploadFunc(rowId, fileInput);
+                    setTimeout(() => {
+                        const $newTbody = $(`#${rowId}`).closest('table').find('tbody[id^="workAccountList_"]:not(.sortable-initialized)');
+                        if ($newTbody.length) {
+                            initTbodySortable($newTbody);
+                        }
+                    }, 500);
+                };
+            }
+        }
+
+        // 初始化单个tbody的拖拽
+        function initTbodySortable($tbody) {
+            if ($tbody.hasClass('sortable-initialized')) return;
+            $tbody.addClass('sortable-initialized');
+
+            // 用自定义数据属性标记是否正在拖拽(替代instance方法)
+            $tbody.data('isSorting', false);
+
+            $tbody.sortable({
+                items: 'tr:not(.summary-row)',
+                helper: fixHelperModified,
+                stop: function() {
+                    updateIndependentIndex($tbody);
+                    // 拖拽结束,标记为false
+                    $tbody.data('isSorting', false);
+                },
+                update: function() {
+                    syncSortOrder($tbody);
+                },
+                containment: $tbody,
+                appendTo: 'body',
+                zIndex: 10000,
+                cancel: '',
+                handle: '',
+                start: function() {
+                    console.log('拖拽开始');
+                    // 拖拽开始,标记为true
+                    $tbody.data('isSorting', true);
+                }
+            }).disableSelection();
+
+            // 处理只读input的点击事件(用自定义数据属性判断)
+            $tbody.find('input[readonly]').on('mousedown', function(e) {
+                if (e.which !== 1) return; // 只处理左键
+
+                const $tr = $(this).closest('tr:not(.summary-row)');
+                if ($tr.length && !$tbody.data('isSorting')) { // 这里替换instance判断
+                    // 手动触发tr的mousedown,模拟拖拽
+                    $tr.trigger('mousedown', [e]);
+                }
+            });
+        }
+
+        // 保持拖拽时单元格宽度
+        function fixHelperModified(e, tr) {
+            const $originals = tr.children();
+            const $helper = tr.clone();
+            $helper.children().each(function(index) {
+                $(this).width($originals.eq(index).width());
+            });
+            return $helper;
+        }
+
+        // 核心优化:每个tbody独立计算序号(从1开始)
+        function updateIndependentIndex($currentTbody) {
+            // 强制确认当前tbody是否有效
+            if (!$currentTbody || !$currentTbody.length) {
+                console.error("错误:未找到有效的tbody元素");
+                return;
+            }
+
+            // 获取tbody的id(兜底处理)
+            const tbodyId = $currentTbody.attr('id') || "匿名tbody";
+
+            // 遍历可拖拽行
+            const $rows = $currentTbody.find('tr:not(.summary-row)');
+            if (!$rows.length) {
+                console.log("[Input统计] tbody[" + tbodyId + "] 内没有可拖拽的行");
+                return;
+            }
+
+            $rows.each(function(rowIndex) {
+                const rowNum = rowIndex + 1;
+                if (isNaN(rowNum)) {
+                    console.warn("[警告] tbody[" + tbodyId + "] 行索引异常:" + rowIndex);
+                    return;
+                }
+
+                const newIndex = rowIndex; // 根据需求调整是否+1
+
+                // 1. 更新序号td
+                const $indexTd = $(this).find('td').eq(2);
+                if ($indexTd.length) {
+                    $indexTd.text(newIndex);
+                } else {
+                    console.warn("[警告] tbody[" + tbodyId + "] 第" + rowNum + "行未找到第三个td");
+                }
+
+                // 2. 处理第一个td中的input
+                const $firstTd = $(this).find('td').eq(0);
+                if (!$firstTd.length) {
+                    console.warn("[警告] tbody[" + tbodyId + "] 第" + rowNum + "行未找到第一个td");
+                    return;
+                }
+
+                const $allInputsInTd = $firstTd.find('input');
+                const totalInputs = $allInputsInTd.length;
+
+
+                const targetInputIndex = 14; // 第15个input(0开始)
+                if (totalInputs > targetInputIndex) {
+                    const $targetInput = $allInputsInTd.eq(targetInputIndex);
+                    $targetInput.val(newIndex);
+                }
+            });
+        }
+
+
+        // 同步排序数据
+        function syncSortOrder($tbody) {
+            $tbody.find('tr:not(.summary-row)').each(function(index) {
+                const sortIndex = index;
+                const $row = $(this);
+
+                const $idInput = $row.find('input[name*="reimbursementElectronicInvoiceVATTaxes"][name*=".id"]');
+                if ($idInput.length) {
+                    const idName = $idInput.attr('name');
+                    const sortName = idName.replace('.id', '.sort');
+                    let $sortInput = $row.find(`input[name="${sortName}"]`);
+
+                    if ($sortInput.length) {
+                        $sortInput.val(sortIndex);
+                    } else {
+                        $row.find('td:first').append(`
+                    <input type="hidden" name="${sortName}" value="${sortIndex}">
+                `);
+                    }
+                }
+            });
+        }
+
+
+
         /**
          * 插入行数据
          * @param tbodyId
@@ -417,6 +604,7 @@
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_fileSize' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].fileSize' type='hidden' value='" + data.fileSize +"'/>"+
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_divIdType' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].divIdType' type='hidden' value='" + data.divIdType +"'/>" +
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_parentId' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].parentId' type='hidden' value='" + data.parentId + "'/>" +
+                "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_indexNumber' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].indexNumber' type='hidden' value='" + data.indexNumber + "'/>" +
                 "</td>"+
 
                 <%--序号--%>
@@ -514,7 +702,6 @@
                             "reimbursementId": $("#wId").val()
                         },
                         success:function(data){
-                            console.log(data)
                             if(!data.success){
                                 decideFlag = true
                                 parent.layer.msg(data.message, {icon: 5});
@@ -895,6 +1082,7 @@
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_fileSize' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].fileSize' type='hidden' value=''/>"+
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_divIdType' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].divIdType' type='hidden' value=''/>" +
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_parentId' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].parentId' type='hidden' value='" + tbodyId + "'/>" +
+                "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_indexNumber' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].indexNumber' type='hidden' value=''/>" +
                 "</td>"+
 
                 <%--序号--%>
@@ -1122,8 +1310,6 @@
 
         // 处理文件上传
         async function handleFileNewUpload(file, size, trlen,inputId,parentIndex) {
-            console.log("inputId",inputId)
-            console.log("parentIndex",parentIndex)
 
             const $tbody = $(inputId);
 
@@ -1363,10 +1549,6 @@
 
         // 数电发票删除 - 隐藏行版本(保留DOM,只隐藏)
         function delRowNew(obj, prefix, parentIndex) {
-            console.log("===== 开始执行delRowNew函数 =====");
-            console.log("当前删除按钮元素:", obj);
-            console.log("prefix参数:", prefix);
-            console.log("parentIndex参数:", parentIndex);
 
             // 获取相关元素
             var $idInput = $(prefix + "_id");
@@ -1379,40 +1561,32 @@
             var $targetInput = $currentRow.find("td:first-child input:eq(1)");
             if ($targetInput.length > 0) {
                 $targetInput.val("1");
-                console.log("已将删除标记设为1");
             }
 
             // 隐藏当前行
             $currentRow.addClass("hidden");
-            console.log("已隐藏当前行");
 
             // 处理父表格显示状态(根据可见行数量)
             if ($parentTable.length > 0) {
                 // 筛选非空且未隐藏的行
                 var visibleRows = $parentTable.find("tr:not(:empty):not(.hidden)");
-                console.log("父表格可见行数:", visibleRows.length);
 
                 // 控制表格显示/隐藏
                 if (visibleRows.length === 0) {
                     $parentTable.hide();
-                    console.log("父表格已隐藏(无可见行)");
                 } else {
                     $parentTable.show();
-                    console.log("父表格已显示");
                 }
 
                 // 隐藏关联行(如果有idValue)
                 if (idValue) {
                     var targetTrClass = idValue;
                     $parentTable.find("tr." + targetTrClass).addClass("hidden");
-                    console.log("已隐藏关联行(class: " + targetTrClass + ")");
                 }
             }
 
-            console.log("展示parentTable: ",$parentTable)
             // 重新排序行号
             reorderRowNumbers($parentTable);
-            console.log("已重新排序行号");
 
             // 查找当前行所在的tbody并获取其id
             const td = obj.closest('td');
@@ -1423,24 +1597,20 @@
             //对数据进行重新处理
             updateSummaryRow("#" + tbodyId)
 
-            console.log("查找的tbodyId:", tbodyId);
             if (!tbodyId) {
                 console.error("未找到有效的tbody,终止金额汇总");
                 return;
             }
 
             // 汇总金额和有效行数(核心修复:选择器添加#前缀)
-            console.log("开始汇总金额,目标tbody选择器: #", tbodyId);
             var total = 0;
             var validRowCount = 0;
 
             // 修复选择器:通过# + tbodyId定位元素
             $("#" + tbodyId).find('tr').each(function(index, tr) {
-                console.log("正在处理第", index + 1, "行");
 
                 // 验证行是否可见(非隐藏)
                 if ($(tr).hasClass("hidden")) {
-                    console.log("第", index + 1, "行是隐藏行,跳过");
                     return true; // 继续下一行
                 }
 
@@ -1448,16 +1618,13 @@
                 var $firstTd = $(tr).find('td').eq(0);
                 var $secondInput = $firstTd.find('input').eq(1);
                 var secondInputValue = $secondInput.val() || '';
-                console.log("第", index + 1, "行的删除标记值:", secondInputValue.trim());
 
                 if (secondInputValue.trim() !== '0') {
-                    console.log("第", index + 1, "行不符合条件,跳过");
                     return true; // 继续下一行
                 }
 
                 // 累加有效行数
                 validRowCount++;
-                console.log("第", index + 1, "行有效,累计有效行数:", validRowCount);
 
                 // 汇总第八个td中第一个input的值
                 var $eighthTd = $(tr).find('td').eq(8);
@@ -1466,12 +1633,10 @@
                 var num = parseFloat(value);
                 var addAmount = isNaN(num) ? 0 : num;
                 total += addAmount;
-                console.log("第", index + 1, "行金额:", addAmount, "当前累计总金额:", total);
             });
 
             // 处理汇总结果(保留两位小数)
             total = total.toFixed(2) * 1;
-            console.log("最终汇总金额:", total, "有效行数:", validRowCount);
 
             // 更新数电发票金额和数量输入框
             var $eInvoiceMoney = $("#workAccountList" + parentIndex + "_eInvoiceMoney");
@@ -1479,15 +1644,10 @@
 
             $eInvoiceMoney.val(total);
             $eInvoiceBills.val(validRowCount);
-            console.log("已更新金额输入框:", $eInvoiceMoney.val(), "数量输入框:", $eInvoiceBills.val());
 
             // 调用汇总方法(修复变量重复声明问题)
             var sumResult = calculateSum(parentIndex);
             var billResult = billSum(parentIndex);
-            console.log("calculateSum结果:", sumResult);
-            console.log("billSum结果:", billResult);
-
-            console.log("===== delRowNew函数执行结束 =====");
         }
 
         // 重新排序行号的函数(只处理未隐藏的行,行号在第二个td中)
@@ -2549,7 +2709,6 @@
             }
 
             var idc = $("#workAccountList" + rowIndex + "_id").val();
-            console.log("idc", idc);
 
             // 1. 校验idc有效性,避免查找无效元素
             if (!idc || idc.trim() === "") {
@@ -2603,7 +2762,6 @@
                 }
             });
 
-            console.log('数电票可报销的最大额度:', maxMoney.toFixed(2));
 
 
             // 4. 计算当前行的金额(单行汇总)
@@ -2626,7 +2784,6 @@
             totalAllInvoice += invoice;
             totalAllSum += rowSum;
 
-            console.log("计算汇总金额",eInvoice)
         });
 
         // 7. 重新计算总报销费用(传入所有行的非数电票总金额)

+ 25 - 0
src/main/webapp/webpage/modules/workreimbursement/treeForm/new/workReimbursementNewAudit.jsp

@@ -397,6 +397,25 @@
             confirmIdNewList = allDataNewList.filter(item => item.vatTaxStatus === '1').map(item => item.id);
         }
 
+        function allSelect(status){
+            // 直接解析后端返回的JSON字符串(无需字符串替换)
+            var allIds = JSON.parse('${reimbursementElectronicInvoiceVATTaxeIdList}');
+
+            // 验证是否为数组
+            if (Array.isArray(allIds)) {
+                allIds.forEach(function(id) {
+                    if (id) { // 过滤空id
+                        newChangeStatus(status, id);
+                        console.log("调用newChangeStatus,id:", id);
+                    }
+                });
+            } else {
+                console.log("id列表格式错误");
+            }
+
+
+        }
+
 
         function newChangeStatus(status, id) {
             console.log("进入newChangeStatus方法",status,id)
@@ -835,6 +854,12 @@
 
             <div class="form-group layui-row">
                 <div class="form-group-label"><h2>报销详情</h2></div>
+
+                <!-- 新增按钮:同样设置底部对齐,确保与标题下方平齐 -->
+                <div class="layui-item nav-btns" style="display: inline-block; ">
+                    <a class="nav-btn nav-btn-add" onclick="allSelect('1')" title="全部确认">全部确认</a>
+                    <a class="nav-btn nav-btn-delete" onclick="allSelect('0')" title="全部取消">全部取消</a>
+                </div>
                 <div class="layui-table-body layui-item layui-col-xs12 form-table-container"  style="padding:0px">
                     <table id="contentTable" class="table table-bordered table-condensed can-edit no-bottom-margin details tree_table">
                         <thead>

+ 206 - 14
src/main/webapp/webpage/modules/workreimbursement/treeForm/new/workReimbursementNewFormAdd.jsp

@@ -102,6 +102,14 @@
             });
             // getRandom();
 
+            // 初始化现有tbody
+            initExistingTbodys();
+            // 监听动态生成的tbody
+            setupDOMObserver();
+            // 覆盖上传回调
+            overrideUploadCallback();
+
+
             laydate.render({
                 elem: '#invoiceDate', //目标元素。由于laydate.js封装了一个轻量级的选择器引擎,因此elem还允许你传入class、tag但必须按照这种方式 '#id .class'
                 event: 'focus', //响应事件。如果没有传入event,则按照默认的click
@@ -353,6 +361,182 @@
 
 
 
+        // 初始化页面已存在的tbody
+        function initExistingTbodys() {
+            $('tbody[id^="workAccountList_"]:not(.sortable-initialized)').each(function() {
+                initTbodySortable($(this));
+            });
+        }
+
+        // 监听DOM变化
+        function setupDOMObserver() {
+            const tableContainer = document.getElementById('contentTable');
+            if (!tableContainer) return;
+
+            const observer = new MutationObserver(function(mutations) {
+                mutations.forEach(function(mutation) {
+                    $(mutation.addedNodes).find('tbody[id^="workAccountList_"]:not(.sortable-initialized)')
+                        .each(function() {
+                            setTimeout(() => {
+                                initTbodySortable($(this));
+                            }, 200);
+                        });
+                });
+            });
+
+            observer.observe(tableContainer, {
+                childList: true,
+                subtree: true
+            });
+        }
+
+        // 覆盖上传回调
+        function overrideUploadCallback() {
+            const originalUploadFunc = window.newInsertTitleInvoiceReimbursement;
+            if (originalUploadFunc) {
+                window.newInsertTitleInvoiceReimbursement = function(rowId, fileInput) {
+                    originalUploadFunc(rowId, fileInput);
+                    setTimeout(() => {
+                        const $newTbody = $(`#${rowId}`).closest('table').find('tbody[id^="workAccountList_"]:not(.sortable-initialized)');
+                        if ($newTbody.length) {
+                            initTbodySortable($newTbody);
+                        }
+                    }, 500);
+                };
+            }
+        }
+
+        function initTbodySortable($tbody) {
+            if ($tbody.hasClass('sortable-initialized')) return;
+            $tbody.addClass('sortable-initialized');
+
+            // 用自定义数据属性标记是否正在拖拽(替代instance方法)
+            $tbody.data('isSorting', false);
+
+            $tbody.sortable({
+                items: 'tr:not(.summary-row)',
+                helper: fixHelperModified,
+                stop: function() {
+                    updateIndependentIndex($tbody);
+                    // 拖拽结束,标记为false
+                    $tbody.data('isSorting', false);
+                },
+                update: function() {
+                    syncSortOrder($tbody);
+                },
+                containment: $tbody,
+                appendTo: 'body',
+                zIndex: 10000,
+                cancel: '',
+                handle: '',
+                start: function() {
+                    console.log('拖拽开始');
+                    // 拖拽开始,标记为true
+                    $tbody.data('isSorting', true);
+                }
+            }).disableSelection();
+
+            // 处理只读input的点击事件(用自定义数据属性判断)
+            $tbody.find('input[readonly]').on('mousedown', function(e) {
+                if (e.which !== 1) return; // 只处理左键
+
+                const $tr = $(this).closest('tr:not(.summary-row)');
+                if ($tr.length && !$tbody.data('isSorting')) { // 这里替换instance判断
+                    // 手动触发tr的mousedown,模拟拖拽
+                    $tr.trigger('mousedown', [e]);
+                }
+            });
+        }
+
+        // 其他辅助函数保持不变
+        function fixHelperModified(e, tr) {
+            const $originals = tr.children();
+            const $helper = tr.clone();
+            $helper.children().each(function(index) {
+                $(this).width($originals.eq(index).width());
+            });
+            return $helper;
+        }
+
+        // 核心优化:每个tbody独立计算序号(从1开始)
+        function updateIndependentIndex($currentTbody) {
+            // 强制确认当前tbody是否有效
+            if (!$currentTbody || !$currentTbody.length) {
+                console.error("错误:未找到有效的tbody元素");
+                return;
+            }
+
+            // 获取tbody的id(兜底处理)
+            const tbodyId = $currentTbody.attr('id') || "匿名tbody";
+
+            // 遍历可拖拽行
+            const $rows = $currentTbody.find('tr:not(.summary-row)');
+            if (!$rows.length) {
+                console.log("[Input统计] tbody[" + tbodyId + "] 内没有可拖拽的行");
+                return;
+            }
+
+            $rows.each(function(rowIndex) {
+                const rowNum = rowIndex + 1;
+                if (isNaN(rowNum)) {
+                    console.warn("[警告] tbody[" + tbodyId + "] 行索引异常:" + rowIndex);
+                    return;
+                }
+
+                const newIndex = rowIndex; // 根据需求调整是否+1
+
+                // 1. 更新序号td
+                const $indexTd = $(this).find('td').eq(2);
+                if ($indexTd.length) {
+                    $indexTd.text(newIndex);
+                } else {
+                    console.warn("[警告] tbody[" + tbodyId + "] 第" + rowNum + "行未找到第三个td");
+                }
+
+                // 2. 处理第一个td中的input
+                const $firstTd = $(this).find('td').eq(0);
+                if (!$firstTd.length) {
+                    console.warn("[警告] tbody[" + tbodyId + "] 第" + rowNum + "行未找到第一个td");
+                    return;
+                }
+
+                const $allInputsInTd = $firstTd.find('input');
+                const totalInputs = $allInputsInTd.length;
+
+
+                const targetInputIndex = 14; // 第15个input(0开始)
+                if (totalInputs > targetInputIndex) {
+                    const $targetInput = $allInputsInTd.eq(targetInputIndex);
+                    $targetInput.val(newIndex);
+                }
+            });
+        }
+
+
+        // 同步排序数据
+        function syncSortOrder($tbody) {
+            $tbody.find('tr:not(.summary-row)').each(function(index) {
+                const sortIndex = index;
+                const $row = $(this);
+
+                const $idInput = $row.find('input[name*="reimbursementElectronicInvoiceVATTaxes"][name*=".id"]');
+                if ($idInput.length) {
+                    const idName = $idInput.attr('name');
+                    const sortName = idName.replace('.id', '.sort');
+                    let $sortInput = $row.find(`input[name="${sortName}"]`);
+
+                    if ($sortInput.length) {
+                        $sortInput.val(sortIndex);
+                    } else {
+                        $row.find('td:first').append(`
+                    <input type="hidden" name="${sortName}" value="${sortIndex}">
+                `);
+                    }
+                }
+            });
+        }
+
+
         /**
          * 插入行数据
          * @param tbodyId
@@ -392,6 +576,7 @@
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_fileSize' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].fileSize' type='hidden' value='" + data.fileSize +"'/>"+
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_divIdType' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].divIdType' type='hidden' value='" + data.divIdType +"'/>" +
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_parentId' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].parentId' type='hidden' value='" + data.parentId + "'/>" +
+                "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_indexNumber' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].indexNumber' type='hidden' value='" + data.indexNumber + "'/>" +
                 "</td>"+
 
                 <%--序号--%>
@@ -692,13 +877,26 @@
             }
             var idx1 = $("#workAccountList tr[id^='workAccountList']").length + 1;
 
+            // 筛选出符合条件的tr:id以workAccountList开头,且第一个td中的第二个input值不为1
+            var validTrs = $("#workAccountList tr[id^='workAccountList']").filter(function() {
+                // 找到当前tr下的第一个td
+                var firstTd = $(this).find('td:first');
+                // 找到第一个td中的第二个input(索引从0开始,第二个即eq(1))
+                var secondInput = firstTd.find('input:eq(3)');
+                // 返回值不等于1的情况(注意值是字符串类型,用!== '1'更严谨)
+                return secondInput.val() !== '1';
+            });
+
+            // 符合条件的tr数量加1作为idx1
+            var number = validTrs.length + 1;
+
             if(list == '#workAccountList'){
 
                 tpl = tpl.replace("workAccountList[0].financialSubjects","workAccountList["+idx1+"].financialSubjects");
                 tpl = tpl.replace("workAccountList[0].financialSubjectss","workAccountList["+idx1+"].financialSubjectss");
                 tpl = tpl.replace("not_project_reimbursement_div","not_project_reimbursement_div\" style=\"display:none;\"");
                 tpl = tpl.replace("project_reimbursement_div\" style=\"display:none;\"","project_reimbursement_div");
-                bornTemplete(list, idx, tpl, row, idx1);
+                bornTemplete(list, idx, tpl, row, idx1,number);
                 //将报销人和部门自动赋值
                 // if (idx==0 && flag){
                 var id="#workAccountList"+idx1+"_reimbursementNameId";
@@ -711,15 +909,15 @@
             }
             var idx2 = $("#reimbursementVATTaxes tr").length;
             if(list == '#reimbursementVATTaxes'){
-                bornTemplete(list, idx, tpl, row, idx2);
+                bornTemplete(list, idx, tpl, row, idx2,number);
             }
             if(list == '#reimbursementElectronicInvoiceVATTaxes'){
-                bornTemplete(list, idx, tpl, row, idx2);
+                bornTemplete(list, idx, tpl, row, idx2,number);
             }
         }
-        function bornTemplete(list, idx, tpl, row, idx1){
+        function bornTemplete(list, idx, tpl, row, idx1,number){
             $(list).append(Mustache.render(tpl, {
-                idx: idx+1, delBtn: true, row: row,
+                idx: idx+1, delBtn: true, row: row,number:number,
                 order:idx1 + 1,
             }));
             $(list+idx).find("select").each(function(){
@@ -904,6 +1102,7 @@
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_fileSize' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].fileSize' type='hidden' value=''/>"+
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_divIdType' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].divIdType' type='hidden' value=''/>" +
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_parentId' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].parentId' type='hidden' value='" + tbodyId + "'/>" +
+                "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_indexNumber' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].indexNumber' type='hidden' value=''/>" +
                 "</td>"+
 
                 <%--序号--%>
@@ -1371,10 +1570,6 @@
 
         // 数电发票删除 - 隐藏行版本(保留DOM,只隐藏)
         function delRowNew(obj, prefix, parentIndex) {
-            console.log("===== 开始执行delRowNew函数 =====");
-            console.log("当前删除按钮元素:", obj);
-            console.log("prefix参数:", prefix);
-            console.log("parentIndex参数:", parentIndex);
 
             // 获取相关元素
             var $idInput = $(prefix + "_id");
@@ -2185,7 +2380,7 @@
         <div class="form-group layui-row">
             <div class="form-group-label"><h2>报销详情<span style="color: red;font-size: 14px"> (可在报销单后新增数电发票xml格式的附件获取发票信息)</span></h2></div>
             <div class="layui-item nav-btns">
-                <a class="nav-btn nav-btn-add" onclick="addRow('#workAccountList', workAccountListRowIdx, workAccountListTpl,'',true);workAccountListRowIdx = workAccountListRowIdx + 1;" title="新增"><i class="fa fa-plus"></i>&nbsp;新增</a>
+                <a class="nav-btn nav-btn-add" onclick="addRow('#workAccountList', workAccountListRowIdx, workAccountListTpl,'',true);workAccountListRowIdx = workAccountListRowIdx + 1;" title="新增"><i class="fa fa-plus"></i>&nbsp;新增报销单</a>
             </div>
             <div class="layui-table-body layui-item layui-col-xs12 form-table-container"  style="padding:0px">
                 <table id="contentTable" class="table table-bordered table-condensed can-edit no-bottom-margin details tree_table">
@@ -2321,7 +2516,7 @@
                 <input id="workAccountList{{idx}}_delFlag" name="workAccountList[{{idx}}].delFlag" type="hidden" value="0"/>
             </td>
             <td  onclick='listTr(this)' style="vertical-align: middle;">
-                <span class='default_shut' name="workAccountList{{idx}}.serialNumber" style="padding-right: 15px; "></span>{{idx}}
+                <span class='default_shut' name="workAccountList{{idx}}.serialNumber" style="padding-right: 15px; "></span>{{number}}
             </td>
             <td style="vertical-align: middle;">
                 <div class="project_reimbursement_div"  style="width: 200px">
@@ -2531,7 +2726,6 @@
             }
 
             var idc = $("#workAccountList" + rowIndex + "_id").val();
-            console.log("idc", idc);
 
             // 1. 校验idc有效性,避免查找无效元素
             if (!idc || idc.trim() === "") {
@@ -2585,7 +2779,6 @@
                 }
             });
 
-            console.log('数电票可报销的最大额度:', maxMoney.toFixed(2));
 
 
             // 4. 计算当前行的金额(单行汇总)
@@ -2608,7 +2801,6 @@
             totalAllInvoice += invoice;
             totalAllSum += rowSum;
 
-            console.log("计算汇总金额",eInvoice)
         });
 
         // 7. 重新计算总报销费用(传入所有行的非数电票总金额)

+ 189 - 32
src/main/webapp/webpage/modules/workreimbursement/treeForm/new/workReimbursementNewModifyApply.jsp

@@ -102,6 +102,14 @@
             });
             // getRandom();
 
+
+            // 初始化现有tbody
+            initExistingTbodys();
+            // 监听动态生成的tbody
+            setupDOMObserver();
+            // 覆盖上传回调
+            overrideUploadCallback();
+
             laydate.render({
                 elem: '#invoiceDate', //目标元素。由于laydate.js封装了一个轻量级的选择器引擎,因此elem还允许你传入class、tag但必须按照这种方式 '#id .class'
                 event: 'focus', //响应事件。如果没有传入event,则按照默认的click
@@ -377,6 +385,185 @@
 
 
 
+        // 初始化页面已存在的tbody
+        function initExistingTbodys() {
+            $('tbody[id^="workAccountList_"]:not(.sortable-initialized)').each(function() {
+                initTbodySortable($(this));
+            });
+        }
+
+        // 监听DOM变化
+        function setupDOMObserver() {
+            const tableContainer = document.getElementById('contentTable');
+            if (!tableContainer) return;
+
+            const observer = new MutationObserver(function(mutations) {
+                mutations.forEach(function(mutation) {
+                    $(mutation.addedNodes).find('tbody[id^="workAccountList_"]:not(.sortable-initialized)')
+                        .each(function() {
+                            setTimeout(() => {
+                                initTbodySortable($(this));
+                            }, 200);
+                        });
+                });
+            });
+
+            observer.observe(tableContainer, {
+                childList: true,
+                subtree: true
+            });
+        }
+
+        // 覆盖上传回调
+        function overrideUploadCallback() {
+            const originalUploadFunc = window.newInsertTitleInvoiceReimbursement;
+            if (originalUploadFunc) {
+                window.newInsertTitleInvoiceReimbursement = function(rowId, fileInput) {
+                    originalUploadFunc(rowId, fileInput);
+                    setTimeout(() => {
+                        const $newTbody = $(`#${rowId}`).closest('table').find('tbody[id^="workAccountList_"]:not(.sortable-initialized)');
+                        if ($newTbody.length) {
+                            initTbodySortable($newTbody);
+                        }
+                    }, 500);
+                };
+            }
+        }
+
+        // 初始化单个tbody的拖拽
+        function initTbodySortable($tbody) {
+            if ($tbody.hasClass('sortable-initialized')) return;
+            $tbody.addClass('sortable-initialized');
+
+            // 用自定义数据属性标记是否正在拖拽(替代instance方法)
+            $tbody.data('isSorting', false);
+
+            $tbody.sortable({
+                items: 'tr:not(.summary-row)',
+                helper: fixHelperModified,
+                stop: function() {
+                    updateIndependentIndex($tbody);
+                    // 拖拽结束,标记为false
+                    $tbody.data('isSorting', false);
+                },
+                update: function() {
+                    syncSortOrder($tbody);
+                },
+                containment: $tbody,
+                appendTo: 'body',
+                zIndex: 10000,
+                cancel: '',
+                handle: '',
+                start: function() {
+                    console.log('拖拽开始');
+                    // 拖拽开始,标记为true
+                    $tbody.data('isSorting', true);
+                }
+            }).disableSelection();
+
+            // 处理只读input的点击事件(用自定义数据属性判断)
+            $tbody.find('input[readonly]').on('mousedown', function(e) {
+                if (e.which !== 1) return; // 只处理左键
+
+                const $tr = $(this).closest('tr:not(.summary-row)');
+                if ($tr.length && !$tbody.data('isSorting')) { // 这里替换instance判断
+                    // 手动触发tr的mousedown,模拟拖拽
+                    $tr.trigger('mousedown', [e]);
+                }
+            });
+        }
+
+        // 保持拖拽时单元格宽度
+        function fixHelperModified(e, tr) {
+            const $originals = tr.children();
+            const $helper = tr.clone();
+            $helper.children().each(function(index) {
+                $(this).width($originals.eq(index).width());
+            });
+            return $helper;
+        }
+
+        // 核心优化:每个tbody独立计算序号(从1开始)
+        function updateIndependentIndex($currentTbody) {
+            // 强制确认当前tbody是否有效
+            if (!$currentTbody || !$currentTbody.length) {
+                console.error("错误:未找到有效的tbody元素");
+                return;
+            }
+
+            // 获取tbody的id(兜底处理)
+            const tbodyId = $currentTbody.attr('id') || "匿名tbody";
+
+            // 遍历可拖拽行
+            const $rows = $currentTbody.find('tr:not(.summary-row)');
+            if (!$rows.length) {
+                console.log("[Input统计] tbody[" + tbodyId + "] 内没有可拖拽的行");
+                return;
+            }
+
+            $rows.each(function(rowIndex) {
+                const rowNum = rowIndex + 1;
+                if (isNaN(rowNum)) {
+                    console.warn("[警告] tbody[" + tbodyId + "] 行索引异常:" + rowIndex);
+                    return;
+                }
+
+                const newIndex = rowIndex; // 根据需求调整是否+1
+
+                // 1. 更新序号td
+                const $indexTd = $(this).find('td').eq(2);
+                if ($indexTd.length) {
+                    $indexTd.text(newIndex);
+                } else {
+                    console.warn("[警告] tbody[" + tbodyId + "] 第" + rowNum + "行未找到第三个td");
+                }
+
+                // 2. 处理第一个td中的input
+                const $firstTd = $(this).find('td').eq(0);
+                if (!$firstTd.length) {
+                    console.warn("[警告] tbody[" + tbodyId + "] 第" + rowNum + "行未找到第一个td");
+                    return;
+                }
+
+                const $allInputsInTd = $firstTd.find('input');
+                const totalInputs = $allInputsInTd.length;
+
+
+                const targetInputIndex = 14; // 第15个input(0开始)
+                if (totalInputs > targetInputIndex) {
+                    const $targetInput = $allInputsInTd.eq(targetInputIndex);
+                    $targetInput.val(newIndex);
+                }
+            });
+        }
+
+
+        // 同步排序数据
+        function syncSortOrder($tbody) {
+            $tbody.find('tr:not(.summary-row)').each(function(index) {
+                const sortIndex = index;
+                const $row = $(this);
+
+                const $idInput = $row.find('input[name*="reimbursementElectronicInvoiceVATTaxes"][name*=".id"]');
+                if ($idInput.length) {
+                    const idName = $idInput.attr('name');
+                    const sortName = idName.replace('.id', '.sort');
+                    let $sortInput = $row.find(`input[name="${sortName}"]`);
+
+                    if ($sortInput.length) {
+                        $sortInput.val(sortIndex);
+                    } else {
+                        $row.find('td:first').append(`
+                    <input type="hidden" name="${sortName}" value="${sortIndex}">
+                `);
+                    }
+                }
+            });
+        }
+
+
+
+
         /**
          * 插入行数据
          * @param tbodyId
@@ -417,6 +604,7 @@
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_fileSize' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].fileSize' type='hidden' value='" + data.fileSize +"'/>"+
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_divIdType' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].divIdType' type='hidden' value='" + data.divIdType +"'/>" +
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_parentId' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].parentId' type='hidden' value='" + data.parentId + "'/>" +
+                "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_indexNumber' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].indexNumber' type='hidden' value='" + data.indexNumber + "'/>" +
                 "</td>"+
 
                 <%--序号--%>
@@ -514,7 +702,6 @@
                             "reimbursementId": $("#wId").val()
                         },
                         success:function(data){
-                            console.log(data)
                             if(!data.success){
                                 decideFlag = true
                                 parent.layer.msg(data.message, {icon: 5});
@@ -895,6 +1082,7 @@
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_fileSize' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].fileSize' type='hidden' value=''/>"+
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_divIdType' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].divIdType' type='hidden' value=''/>" +
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_parentId' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].parentId' type='hidden' value='" + tbodyId + "'/>" +
+                "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_indexNumber' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].indexNumber' type='hidden' value=''/>" +
                 "</td>"+
 
                 <%--序号--%>
@@ -1119,8 +1307,6 @@
 
         // 处理文件上传
         async function handleFileNewUpload(file, size, trlen,inputId,parentIndex) {
-            console.log("inputId",inputId)
-            console.log("parentIndex",parentIndex)
 
             const $tbody = $(inputId);
 
@@ -1360,10 +1546,6 @@
 
         // 数电发票删除 - 隐藏行版本(保留DOM,只隐藏)
         function delRowNew(obj, prefix, parentIndex) {
-            console.log("===== 开始执行delRowNew函数 =====");
-            console.log("当前删除按钮元素:", obj);
-            console.log("prefix参数:", prefix);
-            console.log("parentIndex参数:", parentIndex);
 
             // 获取相关元素
             var $idInput = $(prefix + "_id");
@@ -1376,40 +1558,32 @@
             var $targetInput = $currentRow.find("td:first-child input:eq(1)");
             if ($targetInput.length > 0) {
                 $targetInput.val("1");
-                console.log("已将删除标记设为1");
             }
 
             // 隐藏当前行
             $currentRow.addClass("hidden");
-            console.log("已隐藏当前行");
 
             // 处理父表格显示状态(根据可见行数量)
             if ($parentTable.length > 0) {
                 // 筛选非空且未隐藏的行
                 var visibleRows = $parentTable.find("tr:not(:empty):not(.hidden)");
-                console.log("父表格可见行数:", visibleRows.length);
 
                 // 控制表格显示/隐藏
                 if (visibleRows.length === 0) {
                     $parentTable.hide();
-                    console.log("父表格已隐藏(无可见行)");
                 } else {
                     $parentTable.show();
-                    console.log("父表格已显示");
                 }
 
                 // 隐藏关联行(如果有idValue)
                 if (idValue) {
                     var targetTrClass = idValue;
                     $parentTable.find("tr." + targetTrClass).addClass("hidden");
-                    console.log("已隐藏关联行(class: " + targetTrClass + ")");
                 }
             }
 
-            console.log("展示parentTable: ",$parentTable)
             // 重新排序行号
             reorderRowNumbers($parentTable);
-            console.log("已重新排序行号");
 
             // 查找当前行所在的tbody并获取其id
             const td = obj.closest('td');
@@ -1420,24 +1594,20 @@
             //对数据进行重新处理
             updateSummaryRow("#" + tbodyId)
 
-            console.log("查找的tbodyId:", tbodyId);
             if (!tbodyId) {
                 console.error("未找到有效的tbody,终止金额汇总");
                 return;
             }
 
             // 汇总金额和有效行数(核心修复:选择器添加#前缀)
-            console.log("开始汇总金额,目标tbody选择器: #", tbodyId);
             var total = 0;
             var validRowCount = 0;
 
             // 修复选择器:通过# + tbodyId定位元素
             $("#" + tbodyId).find('tr').each(function(index, tr) {
-                console.log("正在处理第", index + 1, "行");
 
                 // 验证行是否可见(非隐藏)
                 if ($(tr).hasClass("hidden")) {
-                    console.log("第", index + 1, "行是隐藏行,跳过");
                     return true; // 继续下一行
                 }
 
@@ -1445,16 +1615,13 @@
                 var $firstTd = $(tr).find('td').eq(0);
                 var $secondInput = $firstTd.find('input').eq(1);
                 var secondInputValue = $secondInput.val() || '';
-                console.log("第", index + 1, "行的删除标记值:", secondInputValue.trim());
 
                 if (secondInputValue.trim() !== '0') {
-                    console.log("第", index + 1, "行不符合条件,跳过");
                     return true; // 继续下一行
                 }
 
                 // 累加有效行数
                 validRowCount++;
-                console.log("第", index + 1, "行有效,累计有效行数:", validRowCount);
 
                 // 汇总第八个td中第一个input的值
                 var $eighthTd = $(tr).find('td').eq(8);
@@ -1463,12 +1630,10 @@
                 var num = parseFloat(value);
                 var addAmount = isNaN(num) ? 0 : num;
                 total += addAmount;
-                console.log("第", index + 1, "行金额:", addAmount, "当前累计总金额:", total);
             });
 
             // 处理汇总结果(保留两位小数)
             total = total.toFixed(2) * 1;
-            console.log("最终汇总金额:", total, "有效行数:", validRowCount);
 
             // 更新数电发票金额和数量输入框
             var $eInvoiceMoney = $("#workAccountList" + parentIndex + "_eInvoiceMoney");
@@ -1476,15 +1641,10 @@
 
             $eInvoiceMoney.val(total);
             $eInvoiceBills.val(validRowCount);
-            console.log("已更新金额输入框:", $eInvoiceMoney.val(), "数量输入框:", $eInvoiceBills.val());
 
             // 调用汇总方法(修复变量重复声明问题)
             var sumResult = calculateSum(parentIndex);
             var billResult = billSum(parentIndex);
-            console.log("calculateSum结果:", sumResult);
-            console.log("billSum结果:", billResult);
-
-            console.log("===== delRowNew函数执行结束 =====");
         }
 
         // 重新排序行号的函数(只处理未隐藏的行,行号在第二个td中)
@@ -2546,7 +2706,6 @@
             }
 
             var idc = $("#workAccountList" + rowIndex + "_id").val();
-            console.log("idc", idc);
 
             // 1. 校验idc有效性,避免查找无效元素
             if (!idc || idc.trim() === "") {
@@ -2600,7 +2759,6 @@
                 }
             });
 
-            console.log('数电票可报销的最大额度:', maxMoney.toFixed(2));
 
 
             // 4. 计算当前行的金额(单行汇总)
@@ -2623,7 +2781,6 @@
             totalAllInvoice += invoice;
             totalAllSum += rowSum;
 
-            console.log("计算汇总金额",eInvoice)
         });
 
         // 7. 重新计算总报销费用(传入所有行的非数电票总金额)

+ 189 - 32
src/main/webapp/webpage/modules/workreimbursement/treeForm/replenish/workReimbursementReplenishAudit.jsp

@@ -102,6 +102,14 @@
 			});
 			// getRandom();
 
+
+			// 初始化现有tbody
+			initExistingTbodys();
+			// 监听动态生成的tbody
+			setupDOMObserver();
+			// 覆盖上传回调
+			overrideUploadCallback();
+
 			laydate.render({
 				elem: '#invoiceDate', //目标元素。由于laydate.js封装了一个轻量级的选择器引擎,因此elem还允许你传入class、tag但必须按照这种方式 '#id .class'
 				event: 'focus', //响应事件。如果没有传入event,则按照默认的click
@@ -439,6 +447,185 @@
 
 
 
+		// 初始化页面已存在的tbody
+		function initExistingTbodys() {
+			$('tbody[id^="workAccountList_"]:not(.sortable-initialized)').each(function() {
+				initTbodySortable($(this));
+			});
+		}
+
+		// 监听DOM变化
+		function setupDOMObserver() {
+			const tableContainer = document.getElementById('contentTable');
+			if (!tableContainer) return;
+
+			const observer = new MutationObserver(function(mutations) {
+				mutations.forEach(function(mutation) {
+					$(mutation.addedNodes).find('tbody[id^="workAccountList_"]:not(.sortable-initialized)')
+							.each(function() {
+								setTimeout(() => {
+									initTbodySortable($(this));
+								}, 200);
+							});
+				});
+			});
+
+			observer.observe(tableContainer, {
+				childList: true,
+				subtree: true
+			});
+		}
+
+		// 覆盖上传回调
+		function overrideUploadCallback() {
+			const originalUploadFunc = window.newInsertTitleInvoiceReimbursement;
+			if (originalUploadFunc) {
+				window.newInsertTitleInvoiceReimbursement = function(rowId, fileInput) {
+					originalUploadFunc(rowId, fileInput);
+					setTimeout(() => {
+						const $newTbody = $(`#${rowId}`).closest('table').find('tbody[id^="workAccountList_"]:not(.sortable-initialized)');
+						if ($newTbody.length) {
+							initTbodySortable($newTbody);
+						}
+					}, 500);
+				};
+			}
+		}
+
+		// 初始化单个tbody的拖拽
+		function initTbodySortable($tbody) {
+			if ($tbody.hasClass('sortable-initialized')) return;
+			$tbody.addClass('sortable-initialized');
+
+			// 用自定义数据属性标记是否正在拖拽(替代instance方法)
+			$tbody.data('isSorting', false);
+
+			$tbody.sortable({
+				items: 'tr:not(.summary-row)',
+				helper: fixHelperModified,
+				stop: function() {
+					updateIndependentIndex($tbody);
+					// 拖拽结束,标记为false
+					$tbody.data('isSorting', false);
+				},
+				update: function() {
+					syncSortOrder($tbody);
+				},
+				containment: $tbody,
+				appendTo: 'body',
+				zIndex: 10000,
+				cancel: '',
+				handle: '',
+				start: function() {
+					console.log('拖拽开始');
+					// 拖拽开始,标记为true
+					$tbody.data('isSorting', true);
+				}
+			}).disableSelection();
+
+			// 处理只读input的点击事件(用自定义数据属性判断)
+			$tbody.find('input[readonly]').on('mousedown', function(e) {
+				if (e.which !== 1) return; // 只处理左键
+
+				const $tr = $(this).closest('tr:not(.summary-row)');
+				if ($tr.length && !$tbody.data('isSorting')) { // 这里替换instance判断
+					// 手动触发tr的mousedown,模拟拖拽
+					$tr.trigger('mousedown', [e]);
+				}
+			});
+		}
+
+		// 保持拖拽时单元格宽度
+		function fixHelperModified(e, tr) {
+			const $originals = tr.children();
+			const $helper = tr.clone();
+			$helper.children().each(function(index) {
+				$(this).width($originals.eq(index).width());
+			});
+			return $helper;
+		}
+
+		// 核心优化:每个tbody独立计算序号(从1开始)
+		function updateIndependentIndex($currentTbody) {
+			// 强制确认当前tbody是否有效
+			if (!$currentTbody || !$currentTbody.length) {
+				console.error("错误:未找到有效的tbody元素");
+				return;
+			}
+
+			// 获取tbody的id(兜底处理)
+			const tbodyId = $currentTbody.attr('id') || "匿名tbody";
+
+			// 遍历可拖拽行
+			const $rows = $currentTbody.find('tr:not(.summary-row)');
+			if (!$rows.length) {
+				console.log("[Input统计] tbody[" + tbodyId + "] 内没有可拖拽的行");
+				return;
+			}
+
+			$rows.each(function(rowIndex) {
+				const rowNum = rowIndex + 1;
+				if (isNaN(rowNum)) {
+					console.warn("[警告] tbody[" + tbodyId + "] 行索引异常:" + rowIndex);
+					return;
+				}
+
+				const newIndex = rowIndex; // 根据需求调整是否+1
+
+				// 1. 更新序号td
+				const $indexTd = $(this).find('td').eq(2);
+				if ($indexTd.length) {
+					$indexTd.text(newIndex);
+				} else {
+					console.warn("[警告] tbody[" + tbodyId + "] 第" + rowNum + "行未找到第三个td");
+				}
+
+				// 2. 处理第一个td中的input
+				const $firstTd = $(this).find('td').eq(0);
+				if (!$firstTd.length) {
+					console.warn("[警告] tbody[" + tbodyId + "] 第" + rowNum + "行未找到第一个td");
+					return;
+				}
+
+				const $allInputsInTd = $firstTd.find('input');
+				const totalInputs = $allInputsInTd.length;
+
+
+				const targetInputIndex = 14; // 第15个input(0开始)
+				if (totalInputs > targetInputIndex) {
+					const $targetInput = $allInputsInTd.eq(targetInputIndex);
+					$targetInput.val(newIndex);
+				}
+			});
+		}
+
+
+		// 同步排序数据
+		function syncSortOrder($tbody) {
+			$tbody.find('tr:not(.summary-row)').each(function(index) {
+				const sortIndex = index;
+				const $row = $(this);
+
+				const $idInput = $row.find('input[name*="reimbursementElectronicInvoiceVATTaxes"][name*=".id"]');
+				if ($idInput.length) {
+					const idName = $idInput.attr('name');
+					const sortName = idName.replace('.id', '.sort');
+					let $sortInput = $row.find(`input[name="${sortName}"]`);
+
+					if ($sortInput.length) {
+						$sortInput.val(sortIndex);
+					} else {
+						$row.find('td:first').append(`
+                    <input type="hidden" name="${sortName}" value="${sortIndex}">
+                `);
+					}
+				}
+			});
+		}
+
+
+
+
 		/**
 		 * 插入行数据
 		 * @param tbodyId
@@ -479,6 +666,7 @@
 					"<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_fileSize' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].fileSize' type='hidden' value='" + data.fileSize +"'/>"+
 					"<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_divIdType' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].divIdType' type='hidden' value='" + data.divIdType +"'/>" +
 					"<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_parentId' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].parentId' type='hidden' value='" + data.parentId + "'/>" +
+					"<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_indexNumber' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].indexNumber' type='hidden' value='" + data.indexNumber + "'/>" +
 					"</td>"+
 
 					<%--序号--%>
@@ -576,7 +764,6 @@
 							"reimbursementId": $("#wId").val()
 						},
 						success:function(data){
-							console.log(data)
 							if(!data.success){
 								decideFlag = true
 								parent.layer.msg(data.message, {icon: 5});
@@ -957,6 +1144,7 @@
 					"<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_fileSize' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].fileSize' type='hidden' value=''/>"+
 					"<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_divIdType' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].divIdType' type='hidden' value=''/>" +
 					"<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_parentId' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].parentId' type='hidden' value='" + tbodyId + "'/>" +
+					"<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_indexNumber' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].indexNumber' type='hidden' value=''/>" +
 					"</td>"+
 
 					<%--序号--%>
@@ -1120,8 +1308,6 @@
 
 		// 处理文件上传
 		async function handleFileNewUpload(file, size, trlen,inputId,parentIndex) {
-			console.log("inputId",inputId)
-			console.log("parentIndex",parentIndex)
 
 			const $tbody = $(inputId);
 
@@ -1361,10 +1547,6 @@
 
 		// 数电发票删除 - 隐藏行版本(保留DOM,只隐藏)
 		function delRowNew(obj, prefix, parentIndex) {
-			console.log("===== 开始执行delRowNew函数 =====");
-			console.log("当前删除按钮元素:", obj);
-			console.log("prefix参数:", prefix);
-			console.log("parentIndex参数:", parentIndex);
 
 			// 获取相关元素
 			var $idInput = $(prefix + "_id");
@@ -1377,40 +1559,32 @@
 			var $targetInput = $currentRow.find("td:first-child input:eq(1)");
 			if ($targetInput.length > 0) {
 				$targetInput.val("1");
-				console.log("已将删除标记设为1");
 			}
 
 			// 隐藏当前行
 			$currentRow.addClass("hidden");
-			console.log("已隐藏当前行");
 
 			// 处理父表格显示状态(根据可见行数量)
 			if ($parentTable.length > 0) {
 				// 筛选非空且未隐藏的行
 				var visibleRows = $parentTable.find("tr:not(:empty):not(.hidden)");
-				console.log("父表格可见行数:", visibleRows.length);
 
 				// 控制表格显示/隐藏
 				if (visibleRows.length === 0) {
 					$parentTable.hide();
-					console.log("父表格已隐藏(无可见行)");
 				} else {
 					$parentTable.show();
-					console.log("父表格已显示");
 				}
 
 				// 隐藏关联行(如果有idValue)
 				if (idValue) {
 					var targetTrClass = idValue;
 					$parentTable.find("tr." + targetTrClass).addClass("hidden");
-					console.log("已隐藏关联行(class: " + targetTrClass + ")");
 				}
 			}
 
-			console.log("展示parentTable: ",$parentTable)
 			// 重新排序行号
 			reorderRowNumbers($parentTable);
-			console.log("已重新排序行号");
 
 			// 查找当前行所在的tbody并获取其id
 			const td = obj.closest('td');
@@ -1421,24 +1595,20 @@
 			//对数据进行重新处理
 			updateSummaryRow("#" + tbodyId)
 
-			console.log("查找的tbodyId:", tbodyId);
 			if (!tbodyId) {
 				console.error("未找到有效的tbody,终止金额汇总");
 				return;
 			}
 
 			// 汇总金额和有效行数(核心修复:选择器添加#前缀)
-			console.log("开始汇总金额,目标tbody选择器: #", tbodyId);
 			var total = 0;
 			var validRowCount = 0;
 
 			// 修复选择器:通过# + tbodyId定位元素
 			$("#" + tbodyId).find('tr').each(function(index, tr) {
-				console.log("正在处理第", index + 1, "行");
 
 				// 验证行是否可见(非隐藏)
 				if ($(tr).hasClass("hidden")) {
-					console.log("第", index + 1, "行是隐藏行,跳过");
 					return true; // 继续下一行
 				}
 
@@ -1446,16 +1616,13 @@
 				var $firstTd = $(tr).find('td').eq(0);
 				var $secondInput = $firstTd.find('input').eq(1);
 				var secondInputValue = $secondInput.val() || '';
-				console.log("第", index + 1, "行的删除标记值:", secondInputValue.trim());
 
 				if (secondInputValue.trim() !== '0') {
-					console.log("第", index + 1, "行不符合条件,跳过");
 					return true; // 继续下一行
 				}
 
 				// 累加有效行数
 				validRowCount++;
-				console.log("第", index + 1, "行有效,累计有效行数:", validRowCount);
 
 				// 汇总第八个td中第一个input的值
 				var $eighthTd = $(tr).find('td').eq(8);
@@ -1464,12 +1631,10 @@
 				var num = parseFloat(value);
 				var addAmount = isNaN(num) ? 0 : num;
 				total += addAmount;
-				console.log("第", index + 1, "行金额:", addAmount, "当前累计总金额:", total);
 			});
 
 			// 处理汇总结果(保留两位小数)
 			total = total.toFixed(2) * 1;
-			console.log("最终汇总金额:", total, "有效行数:", validRowCount);
 
 			// 更新数电发票金额和数量输入框
 			var $eInvoiceMoney = $("#workAccountList" + parentIndex + "_eInvoiceMoney");
@@ -1477,15 +1642,10 @@
 
 			$eInvoiceMoney.val(total);
 			$eInvoiceBills.val(validRowCount);
-			console.log("已更新金额输入框:", $eInvoiceMoney.val(), "数量输入框:", $eInvoiceBills.val());
 
 			// 调用汇总方法(修复变量重复声明问题)
 			var sumResult = calculateSum(parentIndex);
 			var billResult = billSum(parentIndex);
-			console.log("calculateSum结果:", sumResult);
-			console.log("billSum结果:", billResult);
-
-			console.log("===== delRowNew函数执行结束 =====");
 		}
 
 		// 重新排序行号的函数(只处理未隐藏的行,行号在第二个td中)
@@ -2553,7 +2713,6 @@
 			}
 
 			var idc = $("#workAccountList" + rowIndex + "_id").val();
-			console.log("idc", idc);
 
 			// 1. 校验idc有效性,避免查找无效元素
 			if (!idc || idc.trim() === "") {
@@ -2607,7 +2766,6 @@
 				}
 			});
 
-			console.log('数电票可报销的最大额度:', maxMoney.toFixed(2));
 
 
 			// 4. 计算当前行的金额(单行汇总)
@@ -2630,7 +2788,6 @@
 			totalAllInvoice += invoice;
 			totalAllSum += rowSum;
 
-			console.log("计算汇总金额",eInvoice)
 		});
 
 		// 7. 重新计算总报销费用(传入所有行的非数电票总金额)

+ 189 - 32
src/main/webapp/webpage/modules/workreimbursement/treeForm/specific/workReimbursementSpecificModifyApply.jsp

@@ -102,6 +102,14 @@
             });
             // getRandom();
 
+
+            // 初始化现有tbody
+            initExistingTbodys();
+            // 监听动态生成的tbody
+            setupDOMObserver();
+            // 覆盖上传回调
+            overrideUploadCallback();
+
             laydate.render({
                 elem: '#invoiceDate', //目标元素。由于laydate.js封装了一个轻量级的选择器引擎,因此elem还允许你传入class、tag但必须按照这种方式 '#id .class'
                 event: 'focus', //响应事件。如果没有传入event,则按照默认的click
@@ -377,6 +385,185 @@
 
 
 
+        // 初始化页面已存在的tbody
+        function initExistingTbodys() {
+            $('tbody[id^="workAccountList_"]:not(.sortable-initialized)').each(function() {
+                initTbodySortable($(this));
+            });
+        }
+
+        // 监听DOM变化
+        function setupDOMObserver() {
+            const tableContainer = document.getElementById('contentTable');
+            if (!tableContainer) return;
+
+            const observer = new MutationObserver(function(mutations) {
+                mutations.forEach(function(mutation) {
+                    $(mutation.addedNodes).find('tbody[id^="workAccountList_"]:not(.sortable-initialized)')
+                        .each(function() {
+                            setTimeout(() => {
+                                initTbodySortable($(this));
+                            }, 200);
+                        });
+                });
+            });
+
+            observer.observe(tableContainer, {
+                childList: true,
+                subtree: true
+            });
+        }
+
+        // 覆盖上传回调
+        function overrideUploadCallback() {
+            const originalUploadFunc = window.newInsertTitleInvoiceReimbursement;
+            if (originalUploadFunc) {
+                window.newInsertTitleInvoiceReimbursement = function(rowId, fileInput) {
+                    originalUploadFunc(rowId, fileInput);
+                    setTimeout(() => {
+                        const $newTbody = $(`#${rowId}`).closest('table').find('tbody[id^="workAccountList_"]:not(.sortable-initialized)');
+                        if ($newTbody.length) {
+                            initTbodySortable($newTbody);
+                        }
+                    }, 500);
+                };
+            }
+        }
+
+        // 初始化单个tbody的拖拽
+        function initTbodySortable($tbody) {
+            if ($tbody.hasClass('sortable-initialized')) return;
+            $tbody.addClass('sortable-initialized');
+
+            // 用自定义数据属性标记是否正在拖拽(替代instance方法)
+            $tbody.data('isSorting', false);
+
+            $tbody.sortable({
+                items: 'tr:not(.summary-row)',
+                helper: fixHelperModified,
+                stop: function() {
+                    updateIndependentIndex($tbody);
+                    // 拖拽结束,标记为false
+                    $tbody.data('isSorting', false);
+                },
+                update: function() {
+                    syncSortOrder($tbody);
+                },
+                containment: $tbody,
+                appendTo: 'body',
+                zIndex: 10000,
+                cancel: '',
+                handle: '',
+                start: function() {
+                    console.log('拖拽开始');
+                    // 拖拽开始,标记为true
+                    $tbody.data('isSorting', true);
+                }
+            }).disableSelection();
+
+            // 处理只读input的点击事件(用自定义数据属性判断)
+            $tbody.find('input[readonly]').on('mousedown', function(e) {
+                if (e.which !== 1) return; // 只处理左键
+
+                const $tr = $(this).closest('tr:not(.summary-row)');
+                if ($tr.length && !$tbody.data('isSorting')) { // 这里替换instance判断
+                    // 手动触发tr的mousedown,模拟拖拽
+                    $tr.trigger('mousedown', [e]);
+                }
+            });
+        }
+
+        // 保持拖拽时单元格宽度
+        function fixHelperModified(e, tr) {
+            const $originals = tr.children();
+            const $helper = tr.clone();
+            $helper.children().each(function(index) {
+                $(this).width($originals.eq(index).width());
+            });
+            return $helper;
+        }
+
+        // 核心优化:每个tbody独立计算序号(从1开始)
+        function updateIndependentIndex($currentTbody) {
+            // 强制确认当前tbody是否有效
+            if (!$currentTbody || !$currentTbody.length) {
+                console.error("错误:未找到有效的tbody元素");
+                return;
+            }
+
+            // 获取tbody的id(兜底处理)
+            const tbodyId = $currentTbody.attr('id') || "匿名tbody";
+
+            // 遍历可拖拽行
+            const $rows = $currentTbody.find('tr:not(.summary-row)');
+            if (!$rows.length) {
+                console.log("[Input统计] tbody[" + tbodyId + "] 内没有可拖拽的行");
+                return;
+            }
+
+            $rows.each(function(rowIndex) {
+                const rowNum = rowIndex + 1;
+                if (isNaN(rowNum)) {
+                    console.warn("[警告] tbody[" + tbodyId + "] 行索引异常:" + rowIndex);
+                    return;
+                }
+
+                const newIndex = rowIndex; // 根据需求调整是否+1
+
+                // 1. 更新序号td
+                const $indexTd = $(this).find('td').eq(2);
+                if ($indexTd.length) {
+                    $indexTd.text(newIndex);
+                } else {
+                    console.warn("[警告] tbody[" + tbodyId + "] 第" + rowNum + "行未找到第三个td");
+                }
+
+                // 2. 处理第一个td中的input
+                const $firstTd = $(this).find('td').eq(0);
+                if (!$firstTd.length) {
+                    console.warn("[警告] tbody[" + tbodyId + "] 第" + rowNum + "行未找到第一个td");
+                    return;
+                }
+
+                const $allInputsInTd = $firstTd.find('input');
+                const totalInputs = $allInputsInTd.length;
+
+
+                const targetInputIndex = 14; // 第15个input(0开始)
+                if (totalInputs > targetInputIndex) {
+                    const $targetInput = $allInputsInTd.eq(targetInputIndex);
+                    $targetInput.val(newIndex);
+                }
+            });
+        }
+
+
+        // 同步排序数据
+        function syncSortOrder($tbody) {
+            $tbody.find('tr:not(.summary-row)').each(function(index) {
+                const sortIndex = index;
+                const $row = $(this);
+
+                const $idInput = $row.find('input[name*="reimbursementElectronicInvoiceVATTaxes"][name*=".id"]');
+                if ($idInput.length) {
+                    const idName = $idInput.attr('name');
+                    const sortName = idName.replace('.id', '.sort');
+                    let $sortInput = $row.find(`input[name="${sortName}"]`);
+
+                    if ($sortInput.length) {
+                        $sortInput.val(sortIndex);
+                    } else {
+                        $row.find('td:first').append(`
+                    <input type="hidden" name="${sortName}" value="${sortIndex}">
+                `);
+                    }
+                }
+            });
+        }
+
+
+
+
         /**
          * 插入行数据
          * @param tbodyId
@@ -417,6 +604,7 @@
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_fileSize' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].fileSize' type='hidden' value='" + data.fileSize +"'/>"+
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_divIdType' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].divIdType' type='hidden' value='" + data.divIdType +"'/>" +
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_parentId' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].parentId' type='hidden' value='" + data.parentId + "'/>" +
+                "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_indexNumber' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].indexNumber' type='hidden' value='" + data.indexNumber + "'/>" +
                 "</td>"+
 
                 <%--序号--%>
@@ -514,7 +702,6 @@
                             "reimbursementId": $("#wId").val()
                         },
                         success:function(data){
-                            console.log(data)
                             if(!data.success){
                                 decideFlag = true
                                 parent.layer.msg(data.message, {icon: 5});
@@ -906,6 +1093,7 @@
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_fileSize' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].fileSize' type='hidden' value=''/>"+
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_divIdType' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].divIdType' type='hidden' value=''/>" +
                 "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_parentId' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].parentId' type='hidden' value='" + tbodyId + "'/>" +
+                "<input id='reimbursementElectronicInvoiceVATTaxes" + trLength +"_indexNumber' name='workAccountList[" + parentIndex + "].reimbursementElectronicInvoiceVATTaxes[" + trLength +"].indexNumber' type='hidden' value=''/>" +
                 "</td>"+
 
                 <%--序号--%>
@@ -1133,8 +1321,6 @@
 
         // 处理文件上传
         async function handleFileNewUpload(file, size, trlen,inputId,parentIndex) {
-            console.log("inputId",inputId)
-            console.log("parentIndex",parentIndex)
 
             const $tbody = $(inputId);
 
@@ -1374,10 +1560,6 @@
 
         // 数电发票删除 - 隐藏行版本(保留DOM,只隐藏)
         function delRowNew(obj, prefix, parentIndex) {
-            console.log("===== 开始执行delRowNew函数 =====");
-            console.log("当前删除按钮元素:", obj);
-            console.log("prefix参数:", prefix);
-            console.log("parentIndex参数:", parentIndex);
 
             // 获取相关元素
             var $idInput = $(prefix + "_id");
@@ -1390,40 +1572,32 @@
             var $targetInput = $currentRow.find("td:first-child input:eq(1)");
             if ($targetInput.length > 0) {
                 $targetInput.val("1");
-                console.log("已将删除标记设为1");
             }
 
             // 隐藏当前行
             $currentRow.addClass("hidden");
-            console.log("已隐藏当前行");
 
             // 处理父表格显示状态(根据可见行数量)
             if ($parentTable.length > 0) {
                 // 筛选非空且未隐藏的行
                 var visibleRows = $parentTable.find("tr:not(:empty):not(.hidden)");
-                console.log("父表格可见行数:", visibleRows.length);
 
                 // 控制表格显示/隐藏
                 if (visibleRows.length === 0) {
                     $parentTable.hide();
-                    console.log("父表格已隐藏(无可见行)");
                 } else {
                     $parentTable.show();
-                    console.log("父表格已显示");
                 }
 
                 // 隐藏关联行(如果有idValue)
                 if (idValue) {
                     var targetTrClass = idValue;
                     $parentTable.find("tr." + targetTrClass).addClass("hidden");
-                    console.log("已隐藏关联行(class: " + targetTrClass + ")");
                 }
             }
 
-            console.log("展示parentTable: ",$parentTable)
             // 重新排序行号
             reorderRowNumbers($parentTable);
-            console.log("已重新排序行号");
 
             // 查找当前行所在的tbody并获取其id
             const td = obj.closest('td');
@@ -1434,24 +1608,20 @@
             //对数据进行重新处理
             updateSummaryRow("#" + tbodyId)
 
-            console.log("查找的tbodyId:", tbodyId);
             if (!tbodyId) {
                 console.error("未找到有效的tbody,终止金额汇总");
                 return;
             }
 
             // 汇总金额和有效行数(核心修复:选择器添加#前缀)
-            console.log("开始汇总金额,目标tbody选择器: #", tbodyId);
             var total = 0;
             var validRowCount = 0;
 
             // 修复选择器:通过# + tbodyId定位元素
             $("#" + tbodyId).find('tr').each(function(index, tr) {
-                console.log("正在处理第", index + 1, "行");
 
                 // 验证行是否可见(非隐藏)
                 if ($(tr).hasClass("hidden")) {
-                    console.log("第", index + 1, "行是隐藏行,跳过");
                     return true; // 继续下一行
                 }
 
@@ -1459,16 +1629,13 @@
                 var $firstTd = $(tr).find('td').eq(0);
                 var $secondInput = $firstTd.find('input').eq(1);
                 var secondInputValue = $secondInput.val() || '';
-                console.log("第", index + 1, "行的删除标记值:", secondInputValue.trim());
 
                 if (secondInputValue.trim() !== '0') {
-                    console.log("第", index + 1, "行不符合条件,跳过");
                     return true; // 继续下一行
                 }
 
                 // 累加有效行数
                 validRowCount++;
-                console.log("第", index + 1, "行有效,累计有效行数:", validRowCount);
 
                 // 汇总第八个td中第一个input的值
                 var $eighthTd = $(tr).find('td').eq(8);
@@ -1477,12 +1644,10 @@
                 var num = parseFloat(value);
                 var addAmount = isNaN(num) ? 0 : num;
                 total += addAmount;
-                console.log("第", index + 1, "行金额:", addAmount, "当前累计总金额:", total);
             });
 
             // 处理汇总结果(保留两位小数)
             total = total.toFixed(2) * 1;
-            console.log("最终汇总金额:", total, "有效行数:", validRowCount);
 
             // 更新数电发票金额和数量输入框
             var $eInvoiceMoney = $("#workAccountList" + parentIndex + "_eInvoiceMoney");
@@ -1490,15 +1655,10 @@
 
             $eInvoiceMoney.val(total);
             $eInvoiceBills.val(validRowCount);
-            console.log("已更新金额输入框:", $eInvoiceMoney.val(), "数量输入框:", $eInvoiceBills.val());
 
             // 调用汇总方法(修复变量重复声明问题)
             var sumResult = calculateSum(parentIndex);
             var billResult = billSum(parentIndex);
-            console.log("calculateSum结果:", sumResult);
-            console.log("billSum结果:", billResult);
-
-            console.log("===== delRowNew函数执行结束 =====");
         }
 
         // 重新排序行号的函数(只处理未隐藏的行,行号在第二个td中)
@@ -2560,7 +2720,6 @@
             }
 
             var idc = $("#workAccountList" + rowIndex + "_id").val();
-            console.log("idc", idc);
 
             // 1. 校验idc有效性,避免查找无效元素
             if (!idc || idc.trim() === "") {
@@ -2614,7 +2773,6 @@
                 }
             });
 
-            console.log('数电票可报销的最大额度:', maxMoney.toFixed(2));
 
 
             // 4. 计算当前行的金额(单行汇总)
@@ -2637,7 +2795,6 @@
             totalAllInvoice += invoice;
             totalAllSum += rowSum;
 
-            console.log("计算汇总金额",eInvoice)
         });
 
         // 7. 重新计算总报销费用(传入所有行的非数电票总金额)