You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:实现模态框中序列号的跨选择器互斥显示功能

问题描述

开发了一个包含芯片(chip)和序列号(serial code)的模态框(modal),选择芯片时可切换对应的序列号,但需要实现核心功能:已被某个选择器(select)选中的序列号,不再在其他选择器中显示,目前无法完成该功能,求解决。

现有代码

JavaScript 代码

var chipsSelecionados = [];
$("input[name='inventarios[]']").each(function() {
  var id = $(this).val();
  chipsSelecionados.push(id);
});

var optionsChips = seriais.map(function(seriais) {
  //se o selecionado
  var id = seriais.id;
  if ($.inArray(id.toString(), chipsSelecionados) === -1) {
    return "<option value='" + seriais.id + "'>" + seriais.serial + "</option>";
  }
}).join("");

$('#modal-buscar-linha').modal("hide");

var novaLinha = "<tr>" +
  "<input type='hidden' name='inventarios[]' value='" + idChip + "'>" +
  "<td style='vertical-align: middle;'><select class='form-control' style='margin: 0 auto;'>" + optionsChips + "</select></td>" +
  "<td>" + agenda + "</td>" +
  "<td style='vertical-align: middle;'><select class='form-control' style='margin: 0 auto;'><option>Não selecionar</option>" + options + "</select></td>" +
  "<td class='text-center'>" +
  "<button class='btn btn-danger delete-button' type='button'><i class='fa fa-trash' aria-hidden='true'></i></button>" +
  "</td>" +
  "</tr>";

HTML 依赖

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

解决方案

要实现目标功能,需要实时维护已选序列号集合,并在选择变化时同步更新所有下拉框选项,具体实现步骤如下:

  • 维护全局已选序列号集合:用Set存储已选ID,避免重复,提升增删和存在性检查的效率。
  • 监听所有select的change事件:当选择或取消选择时,更新已选集合,并重新渲染所有select的选项。
  • 封装选项渲染函数:根据当前已选集合,过滤出可选的序列号,生成对应的option元素,同时保留当前select自身的已选值。
  • 处理删除行的情况:删除行时,将该行select选中的序列号从已选集合中移除,并更新其他select的选项。

优化后的JavaScript代码

// 全局存储已选的序列号ID,用Set避免重复
var selectedSerialIds = new Set();

// 初始化:从已存在的行中读取已选序列号
$("tr").find("select:first").each(function() {
  var selectedId = $(this).val();
  if (selectedId) {
    selectedSerialIds.add(selectedId);
  }
});

// 封装渲染select选项的函数
function renderSerialOptions(selectElement, currentSelectedId) {
  var optionsHtml = seriais.map(function(serial) {
    // 排除已选的(除了当前select自己选中的)
    if (!selectedSerialIds.has(serial.id.toString()) || serial.id.toString() === currentSelectedId) {
      var isSelected = serial.id.toString() === currentSelectedId ? "selected" : "";
      return `<option value='${serial.id}' ${isSelected}>${serial.serial}</option>`;
    }
  }).filter(Boolean).join(""); // 过滤掉undefined项
  $(selectElement).html(optionsHtml);
}

// 监听所有select的change事件
$(document).on("change", "tr select:first", function() {
  var prevId = $(this).data("prev-selected");
  var newId = $(this).val();
  
  // 移除之前选中的ID(如果存在)
  if (prevId) {
    selectedSerialIds.delete(prevId);
  }
  // 添加新选中的ID(如果不是空)
  if (newId) {
    selectedSerialIds.add(newId);
  }
  
  // 更新当前select的prev-selected数据
  $(this).data("prev-selected", newId);
  
  // 重新渲染所有select的选项
  $("tr select:first").each(function() {
    renderSerialOptions(this, $(this).val());
  });
});

// 处理添加新行的逻辑(修改原有的novaLinha生成代码)
function addNewRow(idChip, agenda) {
  // 初始化新select的选项:排除已选的
  var optionsChips = seriais.map(function(serial) {
    if (!selectedSerialIds.has(serial.id.toString())) {
      return `<option value='${serial.id}'>${serial.serial}</option>`;
    }
  }).filter(Boolean).join("");

  var novaLinha = `<tr>` +
    `<input type='hidden' name='inventarios[]' value='${idChip}'>` +
    `<td style='vertical-align: middle;'><select class='form-control' style='margin: 0 auto;'>${optionsChips}</select></td>` +
    `<td>${agenda}</td>` +
    `<td style='vertical-align: middle;'><select class='form-control' style='margin: 0 auto;'><option>Não selecionar</option>${options}</select></td>` +
    `<td class='text-center'>` +
    `<button class='btn btn-danger delete-button' type='button'><i class='fa fa-trash' aria-hidden='true'></i></button>` +
    `</td>` +
    `</tr>`;

  // 插入新行到表格(需替换为你的表格tbody选择器)
  $("#table-body").append(novaLinha);
  
  // 隐藏模态框
  $('#modal-buscar-linha').modal("hide");
}

// 处理删除行的逻辑
$(document).on("click", ".delete-button", function() {
  var row = $(this).closest("tr");
  var select = row.find("select:first");
  var selectedId = select.val();
  
  // 从已选集合中移除该ID
  if (selectedId) {
    selectedSerialIds.delete(selectedId);
  }
  
  // 删除行
  row.remove();
  
  // 重新渲染剩余select的选项
  $("tr select:first").each(function() {
    renderSerialOptions(this, $(this).val());
  });
});

关键说明

  • 使用Set替代数组存储已选ID,避免重复值,同时增删和存在性检查的效率更高。
  • 每次select选择变化时,实时更新已选集合并重新渲染所有下拉框,确保已选序列号不会出现在其他下拉框中。
  • 删除行时同步移除对应已选ID,避免残留无效的已选记录。
  • 渲染选项时保留当前select自身的已选值,防止当前下拉框丢失选中状态。

内容的提问来源于stack exchange,提问作者Bernardo Mantoan Castellani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 19:24:54