Jquery onChange文档保存重复问题:仅保存当前激活字段文档
问题描述
使用JQuery的change事件实现文档保存功能时出现重复保存问题:首次保存单个文档正常,但第二次保存时,saveDocument函数会同时提交首次文档与本次选择的新文档。所有文件输入字段均拥有.docs_field类,需修改代码使函数仅保存触发onChange事件的当前输入字段对应的文档。
问题根源
原代码中saveDocument函数会遍历所有文件输入字段,将所有字段的文件都添加到FormData中提交,而非仅处理触发事件的字段;同时AJAX成功回调中重复绑定change事件,会导致事件多次触发的额外问题。
修改方案
1. 前端修改
修改change事件处理逻辑
将当前触发事件的DOM元素传入saveDocument函数,明确指定要处理的目标字段:
$(document).on('change', '.docs_field', function () { if (this.files[0].size > 20971520) { swal("Please select file less then 20MB"); $(this).val(''); } else { // 传递当前触发事件的输入框元素 saveDocument(this); } });
重构saveDocument函数
仅处理传入的目标字段,不再批量收集所有文件:
function saveDocument(inputElement) { var formData = new FormData(); var lead_id = $("#lead-id").val(); formData.append('lead_id', lead_id); // 获取当前输入框的ID作为文档类型标识,兼容带空格的特殊ID var docType = inputElement.id; if (docType === "Signed Loan Application") { docType = "Signed loan Application"; } // 仅将当前选中的文件添加到FormData if (inputElement.files.length > 0) { formData.append(`files[${docType}]`, inputElement.files[0]); } $.ajax({ cache: false, contentType: false, processData: false, headers: { 'X-CSRF-Token': _token }, data: formData, type: "POST", url: base_url + "Leads/saveDocument", success: function (response) { console.log("SUCCESS"); var result = JSON.parse(response); var docu_ids = result['document_id']; // 直接给当前输入框的关联隐藏字段赋值,无需重复绑定事件 $(inputElement).next('.doc_hidden_id').val(docu_ids); } }); }
2. 后端PHP代码优化
增强参数校验逻辑,避免无效数据处理,确保返回正确的文档ID:
function saveDocument(){ Log::write('debug', 'Save document'); $restAPI = new RestAPIHelper(new \Cake\View\View()); if ($this->request->is('Ajax')) { $this->autoRender = false; $data = $this->request->getData(); $field_mapping_arr = array( "Color_Copy_of_Id" => "sales_check_color_copy_id_c", "Color_Copy_of_Id_back" => "sales_check_color_copy_id_back_c", "SSN_Card" => "sales_check_ssn_card_c", "Utility" => "sales_check_utility_bill_c", "Personal_Voided_Check" => "sales_check_ach_voided_check_c", "Business_Voided_Check" => "sales_check_business_voided_check_c", "Personal_Financial_Statment" => "sales_check_financial_statement_c", "Employed" => "sales_check_employed_c", "Remove Fraud Alerts" => "sales_check_remove_fraud_alerts_c", "Self_Employed" => "sales_check_self_employed_c", "Business Debt Schedule" => "sales_check_debt_schedule_c", "Signed loan Application" => "sales_check_signed_application_c", "YTD Profit and Loss Statement" => "sales_check_ytd_balance_sheet_c", "YTD_Balance_Sheet_Statement" => "sales_check_ytd_balance_sheet_statement_c", "SS4_IRSEIN_Letter" => "sales_check_ss4_irsein_letter_c", ); Log::write('debug', "SaveDocument"); Log::write('debug', $data); $files_arr = $data["files"]; $docu_details = []; foreach($files_arr as $document_type => $doc_arr){ Log::write('debug', "doc_arr"); Log::write('debug', $doc_arr); // 严谨判断文件是否有效存在 if(is_array($doc_arr) && isset($doc_arr['tmp_name']) && file_exists($doc_arr['tmp_name'])) { $dataToSave = array ( 'lead_id' => $data["lead_id"], 'document_name' => $doc_arr["name"], 'document_type' => str_replace("_"," ",$document_type), 'template_type' => str_replace("_"," ",$document_type), 'revision' => '1' ); $sendResult = $restAPI->setRecord('Documents', $dataToSave); Log::write("debug", "dataToSave"); Log::write("debug", $dataToSave); // 检查字段映射是否存在,避免Undefined index错误 if(isset($field_mapping_arr[$document_type])){ $dataToSaveForLead = array ( 'id' => $data["lead_id"], $field_mapping_arr[$document_type] => true, ); Log::write("debug", "dataToSaveForLead"); Log::write("debug", $dataToSaveForLead); $sendResultLead = $restAPI->setRecord('Leads', $dataToSaveForLead); } Log::write("debug", "sendResult->id"); Log::write("debug", $sendResult->id); if($sendResult->id){ $docu_details['document_id'] = $sendResult->id; $param = array ( 'note' => array( 'id' => $sendResult->id, 'file' => base64_encode(file_get_contents($doc_arr['tmp_name'])), 'filename' => $doc_arr["name"], 'revision' => '1', ), ); $result = $restAPI->createDocumentRevision($param); } } } ob_clean(); Log::write("debug", "DATA"); Log::write("debug", $docu_details); echo json_encode($docu_details); exit; } }
修改说明
- 前端:通过传递触发事件的元素,精准定位要保存的文档,避免批量提交所有字段;移除重复的事件绑定逻辑,减少冗余触发。
- 后端:增强参数校验,避免无效文件处理;增加字段映射存在性检查,防止报错;因为每次仅提交单个文件,无需担心文档ID覆盖问题。
内容的提问来源于stack exchange,提问作者user20813507
相关产品推荐
相关产品推荐

