复选框联动Report Analysis区域显隐功能实现求助
问题描述
当前Issue区域的选中复选框及Report Analysis数据均从数据库读取。需求是:取消任意复选框勾选时,Report Analysis区域对应隐藏一组数据;勾选新复选框时,新增一组Report Analysis输入项。现有代码未实现该功能,请求修复。
问题诊断
现有代码存在以下核心问题:
- 每次触发
showAnalysisDropdowns都会清空容器后全量重建输入组,无法实现单个复选框对应单个分析组的精准控制 - PHP渲染的历史分析数据与JS生成的新数据分属不同容器,两者无关联,导致勾选状态无法对应到具体数据组
- 复选框重复绑定事件,存在逻辑冲突
- 生成的输入组未与复选框ID关联,无法追踪对应关系
修复方案
1. 调整HTML结构,统一数据容器
将历史分析数据移入#analysisContainer,并给每个分析组添加与复选框对应的data-issue-id标识:
<table> <tr> <td><b> Issue : </b></td> <td> <?php $sql = "SELECT issue_id FROM tblccrs_details WHERE complaintId='" . $_GET['cid'] . "'"; $result = mysqli_query($con, $sql); $issueIdsFromDatabase = array(); while ($row = mysqli_fetch_array($result)) { $explodedList = explode(',', $row['issue_id']); $issueIdsFromDatabase = array_merge($issueIdsFromDatabase, $explodedList); } $issueIdsFromDatabase = array_unique($issueIdsFromDatabase); $issue = mysqli_query($con, "SELECT * FROM list_issue_ts where issue_ts_status='1'"); while ($row = mysqli_fetch_array($issue)) { $issueId = $row['issue_id']; $issueDesc = $row['issue_ts_desc']; $isChecked = in_array($issueId, $issueIdsFromDatabase); echo '<input type="checkbox" name="selectedIssues[]" value="' . $issueId . '" ' . ($isChecked ? 'checked' : '') . '> ' . $issueDesc . '<br>'; } ?> </td> </tr> <tr height="50"> <td colspan="2"> <b>Report Analysis : </b> </td> </tr> <tr> <td colspan="2"> <div id="analysisContainer"> <?php $a = 1; $sql = "SELECT analysis_desc, analysis_sampleNo, analysis_result, analysis_total, issue_id FROM tblccrs_report_analysis WHERE complaintId='" . $_GET['cid'] . "'"; $result = mysqli_query($con, $sql); while ($row = mysqli_fetch_array($result)) { $analysisDesc = $row['analysis_desc']; ?> <div class="analysis-group" data-issue-id="<?php echo $row['issue_id']; ?>"> <label><?php echo $a; ?>. </label> <select name="analysis_data[]" onchange="calculateAnalysisTotal(this)"> <?php $allAnalysisQuery = "SELECT DISTINCT analysis_desc, analysis_value FROM list_report_analysis WHERE analysis_status='1'"; $allAnalysisResult = mysqli_query($con, $allAnalysisQuery); while ($descRow = mysqli_fetch_assoc($allAnalysisResult)) { $selected = ($descRow['analysis_desc'] == $analysisDesc) ? "selected" : ""; echo '<option value="' . $descRow['analysis_value'] . '" data-analysis-desc="' . $descRow['analysis_desc'] . '" ' . $selected . '>' . $descRow['analysis_desc'] . '</option>'; } ?> </select> <br> Sample No: <input type="text" name="analysis_sampleNo[]" value="<?php echo $row['analysis_sampleNo']; ?>"> <br> Result: <input type="text" name="analysis_result[]" value="<?php echo htmlentities(number_format($row['analysis_result'], 2)); ?>"> <br> Exceed: <input type="text" name="analysis_total[]" value="<?php echo htmlentities(number_format($row['analysis_total'], 2)); ?>" readonly> <br> <button type="button" onclick="calculateAnalysisTotal(this)">Calculate</button> <br /> <hr /> </div> <?php $a++;} ?> </div> </td> </tr> </table>
2. 重写JS逻辑,实现复选框与分析组的精准关联
针对单个复选框的变化,仅操作对应的分析组(显示/隐藏/创建):
document.addEventListener('DOMContentLoaded', function() { const issueCheckboxes = document.querySelectorAll('input[name="selectedIssues[]"]'); const analysisContainer = document.getElementById('analysisContainer'); // 预加载分析选项数据 const analysisOptions = <?php $analysis = mysqli_query($con, "SELECT analysis_desc, analysis_value FROM list_report_analysis where analysis_status='1'"); $options = array(); while ($row = mysqli_fetch_array($analysis)) { $options[] = [ 'desc' => $row['analysis_desc'], 'value' => $row['analysis_value'] ]; } echo json_encode($options); ?>; // 初始化:隐藏未勾选复选框对应的分析组 issueCheckboxes.forEach(checkbox => { const issueId = checkbox.value; const existingGroup = analysisContainer.querySelector(`.analysis-group[data-issue-id="${issueId}"]`); if (!checkbox.checked && existingGroup) { existingGroup.style.display = 'none'; } checkbox.addEventListener('change', handleCheckboxChange); }); function handleCheckboxChange(e) { const checkbox = e.target; const issueId = checkbox.value; let analysisGroup = analysisContainer.querySelector(`.analysis-group[data-issue-id="${issueId}"]`); if (checkbox.checked) { if (analysisGroup) { analysisGroup.style.display = 'block'; } else { analysisGroup = createNewAnalysisGroup(issueId); analysisContainer.appendChild(analysisGroup); } } else { if (analysisGroup) { analysisGroup.style.display = 'none'; } } // 控制容器整体显示状态 analysisContainer.style.display = document.querySelector('input[name="selectedIssues[]"]:checked') ? 'block' : 'none'; } // 创建新分析组 function createNewAnalysisGroup(issueId) { const groupDiv = document.createElement('div'); groupDiv.className = 'analysis-group'; groupDiv.setAttribute('data-issue-id', issueId); // 生成下拉选择框 const select = document.createElement('select'); select.name = 'analysis_data[]'; select.innerHTML = '<option value="">Select Report Analysis</option>'; analysisOptions.forEach(opt => { const option = document.createElement('option'); option.value = opt.value; option.textContent = opt.desc; option.setAttribute('data-analysis-desc', opt.desc); select.appendChild(option); }); select.addEventListener('change', calculateAnalysisTotal); // 生成输入框 const sampleNoInput = document.createElement('input'); sampleNoInput.type = 'text'; sampleNoInput.name = 'analysis_sampleNo[]'; sampleNoInput.placeholder = 'Sample No'; const resultInput = document.createElement('input'); resultInput.type = 'text'; resultInput.name = 'analysis_result[]'; resultInput.placeholder = 'Result'; const totalInput = document.createElement('input'); totalInput.type = 'text'; totalInput.name = 'analysis_total[]'; totalInput.placeholder = 'Total Exceed'; totalInput.readOnly = true; // 生成计算按钮 const calcBtn = document.createElement('button'); calcBtn.type = 'button'; calcBtn.textContent = 'Calculate'; calcBtn.addEventListener('click', calculateAnalysisTotal); // 组装元素 groupDiv.appendChild(select); groupDiv.appendChild(document.createElement('br')); groupDiv.appendChild(document.createTextNode('Sample No: ')); groupDiv.appendChild(sampleNoInput); groupDiv.appendChild(document.createElement('br')); groupDiv.appendChild(document.createTextNode('Result: ')); groupDiv.appendChild(resultInput); groupDiv.appendChild(document.createElement('br')); groupDiv.appendChild(document.createTextNode('Exceed: ')); groupDiv.appendChild(totalInput); groupDiv.appendChild(document.createElement('br')); groupDiv.appendChild(calcBtn); groupDiv.appendChild(document.createElement('br')); groupDiv.appendChild(document.createElement('hr')); return groupDiv; } }); // 计算超出值函数 function calculateAnalysisTotal(e) { const group = e.target.closest('.analysis-group'); if (!group) return; const select = group.querySelector('select'); const resultInput = group.querySelector('input[name="analysis_result[]"]'); const totalInput = group.querySelector('input[name="analysis_total[]"]'); const analysisValue = parseFloat(select.value) || 0; const result = parseFloat(resultInput.value) || 0; // 此处可根据实际业务逻辑修改计算方式 totalInput.value = (result - analysisValue).toFixed(2); }
3. 关键修改说明
- 关联标识:通过
data-issue-id绑定复选框与分析组,实现一一对应 - 精准操作:单个复选框变化时仅处理对应分析组,避免全量重建
- 数据预加载:提前将分析选项转为JSON格式传入JS,提升性能
- 统一容器:将历史数据与新增数据纳入同一容器,便于管理
内容的提问来源于stack exchange,提问作者Fatyn Adeline
相关产品推荐
相关产品推荐

