Open Div,Hidden Select ,Flash

本文介绍了一个用于网页的遮罩层和弹出窗口的JavaScript脚本实现方法,包括自适应屏幕尺寸的功能。该脚本适用于IE和Firefox浏览器,并提供了一种简单的方式通过页面元素触发弹窗显示和关闭。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

function Open(){
  //隐藏select控件
  DispalySelect(0); 
  //显示遮罩层
  $("divPageMask").style.display="block";
 //处理遮罩层
  resizeMask();
  window.onResize = resizeMask;
  //显示弹出窗口
  $("divOpenWin").style.display="block";
}
function Close(){
  //显示select控件
  DispalySelect(1);
  //处理遮罩层
  var m = $("divPageMask");
  m.style.width = "0px";
  m.style.height = "0px";
  var o = $("divOpenWin");
  o.style.display = "none";
  window.onResize = null;
  o.style.display="none";
}
//页面遮罩
function resizeMask(){
  var m = $("divPageMask");
  m.style.width = document.documentElement.clientWidth+'px';
  m.style.height = resizeHeight()+'px';
  var o = $("divOpenWin");
   o.style.left = ((document.documentElement.clientWidth - 600) / 2)+'px';
  o.style.top = ((document.documentElement.clientHeight - 400) / 2)+'px';
}
function DispalySelect(val){ 
 //显示和隐藏select控件
  var dispalyType;
   var arrdispalyType=["hidden","visible"];
   var arrObjSelect=document.getElementsByTagName("select");
   for (i=0;i<arrObjSelect.length;i++){
     arrObjSelect[i].style.visibility=arrdispalyType[val];
   }
}
function resizeHeight(){
 var ch = document.documentElement.clientHeight;
 var oh = document.documentElement.scrollHeight;
 if(ch>oh){ return ch;}else{ return oh}
}

 

此脚本只适用于如下的DOCTYPE

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

在IE和FireFox下均正常

HTML:

<div id="divPageMask"></div>
<div id="divOpenWin">
内容区域<a href="javascript:Close();">Close</a>
</div>

 

具体适用方式是:可以通过页面上的某个按钮和超链接触发脚本的Open方法,然后在内容区写上关闭的方法就行了。

上面代码来自网络,感谢贡献者,只是自己增加了resizeHeight方法,因为如果按作者原来的写法只能遮罩文档大小,如果文档内容小于屏幕高度,则不会遮罩下部分,resizeHeight通过比较当前是取文档高度还是屏幕高度。另外要注意的是在设置height和width时要加上px,否则firefox就不认了。

另外别忘记两个div的样式,具体怎么做,你自己修改就行了

#divPageMask{
 background-color:#000000;
 filter:alpha(opacity=50);
 -moz-opacity:.5;
 opacity:0.5;
 left:0px;
 position:absolute;
 top:0px;
}
#divOpenWin{background-color:#FFFFFF;position: absolute;left:0px;top:0px;display: none;z-index:50; width:700px;height:auto}

<div class="container" id="content"> <div class="row"> <div class="col-xs-12 col-sm-12 col-md-5 col-lg-6 hidden-xs hidden-sm"> <h1 class="txt-color-red login-header-big">VisionTool MES 生产制造系统</h1> <div class="hero"> <img class="pull-right display-image" style="width: 380px;" alt="" src="/staticResource/vendor/img/demo/loading.jpg"> </div> </div> <div class="col-xs-12 col-sm-12 col-md-5 col-lg-4"> <div class="well no-padding"> <form class="smart-form client-form" id="login-form" action="index.html"> <header>系统登录认证</header> <fieldset> <section> <label class="label username">用户名</label> <label class="input"> <i class="icon-append fa fa-user"></i> <input name="username" id="username" type="username" placeholder="用户名"> <b class="tooltip tooltip-top-right"><i class="fa fa-user txt-color-teal"></i>请输入用户名</b></label> </section> <section> <label class="label">密码</label> <label class="input"> <i class="icon-append fa fa-lock"></i> <input name="password" id="password" type="password" placeholder="密码"> <b class="tooltip tooltip-top-right"><i class="fa fa-lock txt-color-teal"></i> 请输入密码</b> </label> </section> <section> <label class="label">班次</label> <div class="dropdown bootstrap-select bs3"><select name="shiftClass" tabindex="-98" class="selectpicker" id="shiftClass"></select><button title="Nothing selected" class="btn dropdown-toggle btn-default bs-placeholder" role="combobox" aria-expanded="false" aria-haspopup="listbox" aria-owns="bs-select-1" type="button" data-toggle="dropdown" data-id="shiftClass"><div class="filter-option"><div class="filter-option-inner"><div class="filter-option-inner-inner">Nothing selected</div></div> </div><span class="bs-caret"><span class="caret"></span></span></button><div class="dropdown-menu open"><div tabindex="-1" class="inner open" id="bs-select-1" role="listbox"><ul class="dropdown-menu inner " role="presentation"></ul></div></div></div> </section> <div class="note"> <a onclick="alert('请联系信息管理部:') ">忘记密码了?</a> </div> </fieldset> <footer> <button class="btn btn-primary" id="btnlogin" type="button">登录</button> </footer> </form> </div> </div> </div> </div> 这里面是否包含CSRF令牌信息
06-25
// @ts-nocheck class SweetalertSystem { constructor() { this.fieldRegistry = {}; this.modalRegistry = {}; this.nestedModalStack = []; this.buttonHandlers = new Map(); this.addEntityButtons = null; this.initCoreComponents(); } // ===== 核心字段类型注册 ===== initCoreComponents() { this.registerFieldType('text', { render: (config) => this.renderTextField(config) }); this.registerFieldType('select', { render: (config) => this.renderSelectField(config), afterRender: (element, config) => this.handleSelectAfterRender(element, config) }); this.registerFieldType('number', { render: (config) => this.renderNumberField(config) }); this.registerFieldType('checkbox', { render: (config) => this.renderCheckboxField(config) }); } registerFieldType(type, definition) { if (!definition.render || typeof definition.render !== 'function') { throw new Error(`Field type '${type}' must have a render function`); } this.fieldRegistry[type] = definition; } // ===== 字段渲染方法 ===== renderTextField(config) { return `<div class="mb-3"> <label class="form-label">${config.label}${config.required ? '*' : ''}</label> <input type="text" class="form-control" name="${config.name}" value="${config.value || ''}" ${config.required ? 'required' : ''} placeholder="${config.placeholder || ''}"> </div>`; } renderSelectField(config) { const options = (config.options || []) .map(opt => `<option value="${opt.value}" ${config.value == opt.value ? 'selected' : ''}>${opt.label}</option>`) .join(''); return `<div class="mb-3"> <label class="form-label">${config.label}${config.required ? '*' : ''}</label> <div class="input-group"> <select class="form-select ${config.select2 ? 'select2-field' : ''}" name="${config.name}" ${config.required ? 'required' : ''} placeholder="${config.placeholder || '请选择'}"> <option value=""></option> ${options} </select> ${config.addButton ? ` <button class="btn btn-outline-secondary add-entity-btn" type="button" data-target-field="${config.name}" data-entity-type="${config.addButton.entityType}"> <i class="fa fa-plus"></i> ${config.addButton.label} </button> ` : ''} </div> </div>`; } renderNumberField(config) { return `<div class="mb-3"> <label class="form-label">${config.label}${config.required ? '*' : ''}</label> <input type="number" class="form-control" name="${config.name}" value="${config.value || ''}" ${config.required ? 'required' : ''} step="${config.step || 1}" min="${config.min || 0}"> </div>`; } renderCheckboxField(config) { return `<div class="mb-3 form-check"> <input type="checkbox" class="form-check-input" name="${config.name}" id="${config.name}" ${config.value ? 'checked' : ''}> <label class="form-check-label" for="${config.name}">${config.label}</label> </div>`; } // ===== Select2 处理 ===== handleSelectAfterRender(element, config) { if (config.select2) { const $ select = $(element).find('select'); this.safeInitSelect2($ select, { theme: 'bootstrap', placeholder: config.placeholder || '请选择', allowClear: true, dropdownParent: Swal.getContainer() || document.body }); } } // ===== 表单处理 ===== async openForm(config) { const { title, fields, onSubmit, onAddEntity } = config; const formHTML = fields.map(fieldConfig => { const fieldType = this.fieldRegistry[fieldConfig.type]; return fieldType ? fieldType.render(fieldConfig) : `<div class="error">Field type '${fieldConfig.type}' not supported</div>`; }).join(''); return new Promise((resolve) => { Swal.fire({ title, html: `<form>${formHTML}</form>`, focusConfirm: false, showCancelButton: true, confirmButtonText: config.confirmButtonText || '保存', cancelButtonText: config.cancelButtonText || '取消', preConfirm: () => this.collectFormData(), didOpen: () => { // 处理字段后渲染逻辑 fields.forEach(fieldConfig => { const fieldType = this.fieldRegistry[fieldConfig.type]; if (fieldType && fieldType.afterRender) { const element = Swal.getPopup().querySelector(`[name="${fieldConfig.name}"]`); if (element) { fieldType.afterRender(element, fieldConfig); } } }); // 设置按钮处理器 this.setupMultiButtonHandlers(config, onAddEntity); }, willClose: () => { this.cleanupMultiButtonHandlers(); this.destroyAllSelect2(); } }).then((result) => { if (result.isConfirmed && onSubmit) { onSubmit(result.value); } resolve(result.isConfirmed); }); }); } collectFormData() { const data = {}; const popup = Swal.getPopup(); const form = popup?.querySelector('form'); if (form) { const formData = new FormData(form); for (const [name, value] of formData.entries()) { // 处理多值字段 if (data[name]) { data[name] = Array.isArray(data[name]) ? [...data[name], value] : [data[name], value]; } else { data[name] = value; } } } return data; } // ===== 按钮事件处理 ===== setupMultiButtonHandlers(config, onAddEntity) { const popup = Swal.getPopup(); if (!popup) return; this.cleanupMultiButtonHandlers(); this.addEntityButtons = Array.from(popup.querySelectorAll('.add-entity-btn')); this.addEntityButtons.forEach(btn => { const handler = async () => { const targetField = btn.dataset.targetField; const entityType = btn.dataset.entityType; if (onAddEntity) { const newItem = await onAddEntity(entityType, targetField); if (newItem) { this.updateSelectField(popup, targetField, newItem); } } }; btn.addEventListener('click', handler); this.buttonHandlers.set(btn, handler); }); } cleanupMultiButtonHandlers() { if (this.addEntityButtons) { this.addEntityButtons.forEach(btn => { const handler = this.buttonHandlers.get(btn); if (handler) { btn.removeEventListener('click', handler); this.buttonHandlers.delete(btn); } }); this.addEntityButtons = null; } } updateSelectField(popup, fieldName, newItem) { if (!popup || !popup.isConnected) return; const select = popup.querySelector(`select[name="${fieldName}"]`); if (select) { const option = new Option(newItem.label, newItem.value, true, true); select.add(option); if ($(select).hasClass('select2-initialized')) { $(select).trigger('change'); } } } // ===== 模态框系统 ===== registerModalType(name, config) { this.modalRegistry[name] = { ...config, afterRender: (config, container) => { config.fields.forEach(fieldConfig => { const fieldType = this.fieldRegistry[fieldConfig.type]; if (fieldType && fieldType.afterRender) { const fieldElement = container.find(`[name="${fieldConfig.name}"]`).closest('.mb-3'); if (fieldElement.length && this.isElementInDOM(fieldElement[0])) { try { fieldType.afterRender(fieldElement[0], fieldConfig); } catch (error) { console.error(`AfterRender error for field ${fieldConfig.name}:`, error); } } } }); } }; } registerEntityForm(entityType, fields) { // 确保 fields 是数组 if (!Array.isArray(fields)) { console.error(`Fields must be an array for entity type: ${entityType}`); return; } this.registerModalType(entityType, { template: `<div class="modal fade" id="${entityType}Modal" tabindex="-1"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="${entityType}Title"></h5> <button type="button" class="btn-close" data-bs-dismiss="modal"></button> </div> <div class="modal-body" id="${entityType}Body"></div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button> <button type="button" class="btn btn-primary" id="${entityType}Submit">保存</button> </div> </div> </div> </div>`, render: (config, container) => { container.find(`#${entityType}Title`).text(config.title); let formHTML = ''; // 使用注册时传入的 fields,而不是 config.fields fields.forEach(fieldConfig => { const fieldType = this.fieldRegistry[fieldConfig.type]; if (fieldType) { formHTML += fieldType.render(fieldConfig); } }); container.find(`#${entityType}Body`).html(formHTML); }, getFormData: (container) => { const formData = {}; container.find('input, select, textarea').each(function() { const $ el = $(this); const name = $ el.attr('name'); if (!name) return; if ($ el.attr('type') === 'checkbox') { formData[name] = $ el.is(':checked'); } else { formData[name] = $ el.val(); } }); return formData; }, bindEvents: (config, container, onSubmit) => { container.find(`#${entityType}Submit`).off('click').on('click', () => { const formData = this.getFormData(container); onSubmit(formData); }); } }); } open(modalType, config, callbacks = {}) { if (!this.modalRegistry[modalType]) { console.error(`Unregistered modal type: ${modalType}`); return null; } const modalConfig = this.modalRegistry[modalType]; const modalId = `${modalType}Modal`; let $ modal = $(`#${modalId}`); // 创建模态框如果不存在 if ($ modal.length === 0) { $ modal = $(modalConfig.template); $('body').append($ modal); } // 重新初始化模态框 if ($ modal.data('bs.modal')) { $ modal.data('bs.modal').dispose(); } // 渲染内容 modalConfig.render(config, $ modal); // 绑定事件 if (modalConfig.bindEvents) { modalConfig.bindEvents(config, $ modal, callbacks.onSubmit || (() => {})); } // 创建Bootstrap模态实例 const modalInstance = new bootstrap.Modal($ modal[0]); modalInstance.show(); // 执行后渲染逻辑 if (modalConfig.afterRender) { modalConfig.afterRender(config, $ modal); } // 添加到模态栈 const modalObj = { hide: () => modalInstance.hide(), show: () => modalInstance.show(), getElement: () => $ modal[0], config }; this.nestedModalStack.push(modalObj); return modalObj; } closeCurrentModal() { if (this.nestedModalStack.length > 0) { const currentModal = this.nestedModalStack.pop(); currentModal.hide(); // 显示上一个模态框 if (this.nestedModalStack.length > 0) { const prevModal = this.nestedModalStack[this.nestedModalStack.length - 1]; prevModal.show(); } } } // 添加辅助方法检查元素是否在 DOM 中 isElementInDOM(element) { return document.body.contains(element); } // 增强的安全 Select2 销毁方法 safeDestroySelect2($ select) { try { // 检查元素是否仍在 DOM 中 if (!$ select || $ select.length === 0 || !this.isElementInDOM($ select[0])) { return false; } // 检查 Select2 是否已初始化 if ($ select.data('select2')) { // 尝试使用官方销毁方法 $ select.select2('destroy'); // 手动清理残留数据 $ select.removeData('select2'); $ select.removeClass('select2-hidden-accessible'); $ select.next('.select2-container').remove(); } $ select.removeClass('select2-initialized'); return true; } catch (error) { console.error('Select2 destruction failed:', error); // 尝试回退清理 try { $ select.removeData('select2'); $ select.removeClass('select2-hidden-accessible'); $ select.next('.select2-container').remove(); } catch (fallbackError) { console.error('Fallback cleanup failed:', fallbackError); } return false; } } // 增强的安全 Select2 初始化方法 safeInitSelect2($ select, options) { try { // 检查元素是否在 DOM 中 if (!$ select || $ select.length === 0 || !this.isElementInDOM($ select[0])) { return false; } // 先尝试销毁已有的实例 this.safeDestroySelect2($ select); // 确保 Select2 可用 if (typeof $.fn.select2 !== 'function') { console.warn('Select2 not available, skipping initialization'); return false; } // 应用安全配置 const safeOptions = { ...options, dropdownParent: options.dropdownParent || document.body }; // 初始化 Select2 $ select.select2(safeOptions); $ select.addClass('select2-initialized'); return true; } catch (error) { console.error('Select2 initialization failed:', error); // 尝试回退到简单选择框 try { $ select.addClass('form-control'); $ select.removeClass('select2-field'); } catch (fallbackError) { console.error('Fallback styling failed:', fallbackError); } return false; } } // ... 其他代码 ... // 在弹窗关闭时清理所有 Select2 实例 destroyAllSelect2() { const popup = Swal.getPopup(); if (popup) { $(popup).find('.select2-initialized').each((index, element) => { this.safeDestroySelect2($(element)); }); } } }完整优化
07-04
<think>我们需要在ReusableModalSystem中支持Select2的渲染。由于Select2需要初始化,我们可以在弹窗渲染后执行初始化代码。同时,为了确保Select2的下拉菜单在模态框中正确显示(避免被遮挡),我们需要设置dropdownParent属性。修改ReusableModalSystem.js:1.在render方法中,如果字段类型是select,则添加一个类名以便后续初始化Select2。2.在弹窗渲染完成后,初始化所有select元素为Select2,并设置dropdownParent为当前模态框。但是,由于我们的弹窗系统是动态渲染的,我们需要在每次弹窗渲染完成后执行Select2的初始化。我们可以在bindEvents之后执行这个操作。另外,我们还需要考虑弹窗关闭时销毁Select2实例以避免内存泄漏。具体步骤:1.在ReusableModalSystem的open方法中,在调用modalDef.render和modalDef.bindEvents之后,初始化Select2。2.在初始化Select2时,设置dropdownParent为当前模态框的内容区域(.modal-content)。3.在弹窗关闭时,销毁Select2实例。注意:由于我们的弹窗模板是固定的,每个弹窗都有一个唯一的ID,我们可以使用这个模态框的容器作为dropdownParent。修改ReusableModalSystem.js的open方法:</think>我将为您修改`ReusableModalSystem.js`,使其支持在弹窗中渲染Select2下拉框。以下是完整的解决方案: ### 修改后的 ReusableModalSystem.js ```javascript // @ts-nocheck export class ReusableModalSystem { constructor() { this.modalRegistry = {}; this.fieldRegistry = {}; this.activeModals = []; this.initCoreComponents(); } // 初始化核心组件(无数据依赖) initCoreComponents() { // 注册基础字段类型 this.registerFieldType('text', { render: (config) => { return `<div class="mb-3"> <label class="form-label">${config.label}${config.required ? '*' : ''}</label> <input type="text" class="form-control" name="${config.name}" value="${config.value || ''}" ${config.required ? 'required' : ''}> </div>`; } }); this.registerFieldType('select', { render: (config) => { let options = '<option value="">请选择</option>'; (config.options || []).forEach(opt => { const selected = config.value == opt.value ? 'selected' : ''; options += `<option value="${opt.value}" ${selected}>${opt.label}</option>`; }); return `<div class="mb-3"> <label class="form-label">${config.label}${config.required ? '*' : ''}</label> <select class="form-select select2-field" name="${config.name}" ${config.required ? 'required' : ''} ${config.select2 ? 'data-select2="true"' : ''} ${config.select2Config ? `data-select2-config='${JSON.stringify(config.select2Config)}'` : ''}> ${options} </select> </div>`; }, afterRender: (element, config) => { if (config.select2) { const $select = $(element).find('select'); const configData = config.select2Config || {}; // 默认配置 const defaultConfig = { theme: 'bootstrap', placeholder: config.placeholder || '请选择', allowClear: true, dropdownParent: $select.closest('.modal') }; // 合并配置 const finalConfig = {...defaultConfig, ...configData}; // 初始化Select2 $select.select2(finalConfig); // 添加创建按钮(如果配置了) if (config.addButton) { const $container = $select.closest('.mb-3'); const $button = $(` <button type="button" class="btn btn-sm btn-outline-secondary mt-2 add-entity-btn" data-entity-type="${config.addButton.entityType}"> <i class="fa fa-plus"></i> ${config.addButton.label} </button> `); $container.append($button); } } } }); // 注册基础弹窗模板 this.registerModalType('baseForm', { template: `<div class="modal fade" id="baseFormModal" tabindex="-1"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="baseFormTitle"></h5> <button type="button" class="btn-close" data-bs-dismiss="modal"></button> </div> <div class="modal-body" id="baseFormBody"></div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button> <button type="button" class="btn btn-primary" id="baseFormSubmit">保存</button> </div> </div> </div> </div>`, render: (config, container) => { container.find('#baseFormTitle').text(config.title); let formHTML = ''; config.fields.forEach(fieldConfig => { const fieldType = this.fieldRegistry[fieldConfig.type]; if (fieldType) { formHTML += fieldType.render(fieldConfig); } }); container.find('#baseFormBody').html(formHTML); }, bindEvents: (config, container, onSubmit) => { container.find('#baseFormSubmit').off('click').on('click', () => { const formData = this.getFormData(container); onSubmit(formData); }); // 绑定创建实体按钮事件 container.find('.add-entity-btn').on('click', function() { const entityType = $(this).data('entity-type'); const title = `创建新${getEntityLabel(entityType)}`; // 打开创建实体模态框 window.parent.modalSystem.open('baseForm', { title: title, fields: getEntityFields(entityType) }, { onSubmit: async (formData) => { try { // 保存新实体 const result = await window.parent.dataManager.addEntity(entityType, formData); if (result.status === 200) { // 刷新父弹窗中的下拉框 const $parentSelect = container.find(`select[name="${$(this).data('target-field')}"]`); if ($parentSelect.length) { const newOption = new Option( result.data.name || result.data.bianhao || formatBancaiInfo(result.data), result.data.id, true, true ); $parentSelect.append(newOption).trigger('change'); } return true; // 关闭弹窗 } else { alert(`创建失败: ${result.text}`); return false; } } catch (error) { console.error('创建实体时出错:', error); alert(`创建失败: ${error.message}`); return false; } } }); }); }, afterRender: (config, container) => { // 执行字段的afterRender回调 config.fields.forEach(fieldConfig => { const fieldType = this.fieldRegistry[fieldConfig.type]; if (fieldType && fieldType.afterRender) { const fieldElement = container.find(`[name="${fieldConfig.name}"]`).closest('.mb-3'); if (fieldElement.length) { fieldType.afterRender(fieldElement[0], fieldConfig); } } }); } }); } // 注册字段类型 registerFieldType(type, definition) { this.fieldRegistry[type] = definition; } // 注册弹窗类型 registerModalType(type, definition) { this.modalRegistry[type] = definition; if (!$(`#${type}Modal`).length) { $('body').append(definition.template); } } // 注册实体表单样式(仅样式,无数据) registerEntityForm(entityType, fieldsConfig) { const modalType = `${entityType}Form`; this.registerModalType(modalType, { extends: 'baseForm', render: (config, container) => { // 使用传入的字段配置 this.modalRegistry.baseForm.render({ ...config, title: config.title || `${config.entity?.id ? '编辑' : '添加'}${this.getEntityLabel(entityType)}`, fields: config.fields || fieldsConfig }, container); } }); return modalType; } // 打开弹窗(数据由外部提供) open(type, config, callbacks = {}) { const modalDef = this.modalRegistry[type]; if (!modalDef) throw new Error(`未注册的弹窗类型: ${type}`); const container = $(`#${type}Modal`); modalDef.render(config, container); if (modalDef.bindEvents) { modalDef.bindEvents(config, container, callbacks.onSubmit || callbacks.onConfirm); } if (modalDef.afterRender) { modalDef.afterRender(config, container); } const modal = new bootstrap.Modal(container[0]); modal.show(); // 存储弹窗实例 this.activeModals.push({ container, modal }); // 绑定关闭事件清理Select2 container.on('hidden.bs.modal', () => { // 销毁所有Select2实例 container.find('.select2-field').each(function() { if ($(this).data('select2')) { $(this).select2('destroy'); } }); // 从活动弹窗中移除 this.activeModals = this.activeModals.filter(m => m.container[0] !== container[0]); }); return { close: () => modal.hide(), update: (newConfig) => { modalDef.render(newConfig, container); if (modalDef.afterRender) { modalDef.afterRender(newConfig, container); } } }; } // 辅助方法 getEntityLabel(entityType) { const labels = { 'bancai': '板材', 'caizhi': '材质', 'mupi': '木皮', 'user': '用户', 'dingdan': '订单', 'chanpin': '产品' }; return labels[entityType] || entityType; } getFormData(container) { const formData = {}; container.find(':input').each(function() { const $input = $(this); const name = $input.attr('name'); const type = $input.attr('type'); if (name) { if (type === 'checkbox') { formData[name] = $input.prop('checked'); } else if ($input.hasClass('select2-field')) { // 处理Select2字段 formData[name] = $input.val(); } else { formData[name] = $input.val(); } } }); return formData; } } // 辅助函数 - 获取实体字段配置 function getEntityFields(entityType) { switch (entityType) { case 'chanpin': return [ { type: 'text', name: 'bianhao', label: '产品编号', required: true } ]; case 'zujian': return [ { type: 'text', name: 'name', label: '组件名称', required: true } ]; case 'bancai': return [ { type: 'number', name: 'houdu', label: '厚度(mm)', required: true, step: 0.1, min: 0.1 }, { type: 'select', name: 'caizhi_id', label: '材质', required: true, select2: true, options: window.parent.dataManager.data.caizhis.map(cz => ({ value: cz.id, label: cz.name })) }, { type: 'select', name: 'mupi1_id', label: '木皮1', select2: true, options: window.parent.dataManager.data.mupis.map(mp => ({ value: mp.id, label: `${mp.name}${mp.you ? ' (油)' : ''}` })) }, { type: 'select', name: 'mupi2_id', label: '木皮2', select2: true, options: window.parent.dataManager.data.mupis.map(mp => ({ value: mp.id, label: `${mp.name}${mp.you ? ' (油)' : ''}` })) } ]; default: return [ { type: 'text', name: 'name', label: '名称', required: true } ]; } } // 辅助函数 - 格式化板材信息 function formatBancaiInfo(bancai) { if (!bancai) return ''; let info = `厚度: ${bancai.houdu}mm, 材质: `; if (bancai.caizhi) { info += bancai.caizhi.name; } if (bancai.mupi1) { info += `, 木皮1: ${bancai.mupi1.name}${bancai.mupi1.you ? ' (油)' : ''}`; } if (bancai.mupi2) { info += `, 木皮2: ${bancai.mupi2.name}${bancai.mupi2.you ? ' (油)' : ''}`; } return info; } // 辅助函数 - 获取实体标签 function getEntityLabel(entityType) { const labels = { 'bancai': '板材', 'caizhi': '材质', 'mupi': '木皮', 'user': '用户', 'dingdan': '订单', 'chanpin': '产品', 'dingdan_chanpin': '订单产品', 'chanpin_zujian': '产品组件' }; return labels[entityType] || entityType; } ``` ### 关键改进说明 1. **Select2集成**: - 在`select`字段类型中添加了`afterRender`回调 - 自动检测`select2`配置属性并初始化Select2组件 - 设置`dropdownParent`确保下拉菜单在模态框中正确显示 2. **创建实体按钮**: - 在`select`字段配置中添加`addButton`属性 - 自动在字段下方添加"创建"按钮 - 按钮点击时打开嵌套弹窗创建新实体 3. **弹窗生命周期管理**: - 添加`afterRender`回调用于字段级初始化 - 弹窗关闭时自动销毁Select2实例 - 维护活动弹窗列表避免内存泄漏 4. **辅助函数**: - 添加`getEntityFields`获取实体字段配置 - 添加`formatBancaiInfo`格式化板材信息 - 添加`getEntityLabel`获取实体标签 ### 使用示例 在`tianjia2.js`中,您可以这样配置带Select2和创建按钮的下拉框: ```javascript // 在showEntityModal函数中配置产品下拉框 { type: 'select', name: 'chanpin_id', label: '产品', required: true, select2: true, // 启用Select2 placeholder: '选择产品或创建新产品', options: chanpinOptions, addButton: { // 添加创建按钮 label: '创建新产品', entityType: 'chanpin' } } ``` ### 嵌套弹窗工作流程 1. 用户在主弹窗点击"创建新产品"按钮 2. 打开嵌套弹窗创建新产品 3. 保存成功后: - 关闭嵌套弹窗 - 自动刷新父弹窗中的产品下拉框 - 新创建的产品会出现在下拉选项中 ### 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值