switchSelect.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /**
  2. * @autho wolfcode
  3. * @description switchSelect.js
  4. * @time 2025年7月23日 16:07:06
  5. */
  6. layui.define(['form'], function (exports) {
  7. let form = layui.form, $ = layui.$;
  8. // 构造函数
  9. let SwitchSelect = function (options) {
  10. this.config = $.extend({
  11. elem: null, // 容器选择器
  12. data: [], // 选项数据 {1:'正常',2:'禁用',3:'删除'} Key => Value 形式
  13. default: '', // 默认值
  14. target: '', // 默认显示形式
  15. name: '', // 表单 name
  16. onSwitch: null, // 切换回调
  17. disabled: false, // 是否禁用
  18. }, options);
  19. this.render();
  20. };
  21. // 原型方法
  22. SwitchSelect.prototype = {
  23. // 渲染组件
  24. render: function () {
  25. let that = this;
  26. let elem = $(this.config.elem);
  27. if (!elem.length) return;
  28. let active, toggleHidden
  29. switch (this.config.target) {
  30. case 'radio':
  31. active = 'radio';
  32. toggleHidden = 'select';
  33. break;
  34. case 'select':
  35. active = 'select';
  36. toggleHidden = 'radio';
  37. break;
  38. default:
  39. active = 'select';
  40. toggleHidden = 'radio';
  41. }
  42. // 创建HTML结构
  43. let html = `
  44. <div class="layui-switch-select">
  45. <div class="toggle-dots">
  46. <span class="dot ${active === 'radio' ? 'active' : ''}" data-target="radio"></span>
  47. <span class="dot ${active === 'select' ? 'active' : ''}" data-target="select"></span>
  48. </div>
  49. <div class="layui-input-block">
  50. <div class="radio-container ${toggleHidden === 'radio' ? 'toggle-hidden' : ''}">${this.generateRadioHtml()}</div>
  51. <div class="select-container ${toggleHidden === 'select' ? 'toggle-hidden' : ''}">
  52. <select name="${this.config.name}" lay-filter="switchSelectFilter_${this.config.name}" class="layui-select">
  53. ${this.generateSelectHtml()}
  54. </select>
  55. </div>
  56. </div>
  57. </div>
  58. `;
  59. elem.html(html);
  60. form.render();
  61. this.bindEvents();
  62. },
  63. // 生成单选框HTML
  64. generateRadioHtml: function () {
  65. let html = '';
  66. $.map(this.config.data, (item, index) => {
  67. let checked = index == this.config.default ? 'checked' : '';
  68. let disabled = this.config.disabled ? 'disabled' : '';
  69. html += `\n<input type="radio" name="${this.config.name}" lay-filter="switchSelectFilter_${this.config.name}" value="${index}" title="${item}" ${checked} ${disabled}>\n`;
  70. });
  71. return html;
  72. },
  73. // 生成下拉框HTML
  74. generateSelectHtml: function () {
  75. let html = '';
  76. $.map(this.config.data, (item, index) => {
  77. let selected = index == this.config.default ? 'selected' : '';
  78. let disabled = this.config.disabled ? 'disabled' : '';
  79. html += `\n<option value="${index}" ${selected} ${disabled}>${item}</option>\n`;
  80. });
  81. return html;
  82. },
  83. // 绑定事件
  84. bindEvents: function () {
  85. let that = this;
  86. let elem = $(this.config.elem);
  87. let radioContainer = elem.find('.radio-container');
  88. let selectContainer = elem.find('.select-container');
  89. let toggleDots = elem.find('.dot');
  90. // 圆点切换事件
  91. toggleDots.on('click', function () {
  92. let target = $(this).data('target');
  93. if (target === 'radio') {
  94. radioContainer.removeClass('toggle-hidden');
  95. selectContainer.addClass('toggle-hidden');
  96. } else {
  97. radioContainer.addClass('toggle-hidden');
  98. selectContainer.removeClass('toggle-hidden');
  99. }
  100. // 更新激活状态
  101. toggleDots.removeClass('active');
  102. $(this).addClass('active');
  103. // 同步数据
  104. that.syncData(target);
  105. // 触发回调
  106. if (typeof that.config.onSwitch === 'function') {
  107. that.config.onSwitch(target);
  108. }
  109. });
  110. // 监听单选按钮变化
  111. form.on('radio', function (data) {
  112. let that = $(this);
  113. let name = $(data.elem).attr('name')
  114. if (that.attr('lay-filter') !== `switchSelectFilter_${name}`) return;
  115. let value = $(data.elem).val()
  116. elem.find(`select[name="${name}"]`).val(value);
  117. form.render('select');
  118. });
  119. // 监听下拉框变化
  120. form.on('select', function (data) {
  121. let name = $(data.elem).attr('name')
  122. if ($(data.elem).attr('lay-filter') !== `switchSelectFilter_${name}`) return;
  123. let value = $(data.elem).val()
  124. elem.find(`input[name="${name}"][value="${value}"]`).prop('checked', true);
  125. form.render('radio');
  126. });
  127. },
  128. // 同步数据
  129. syncData: function (target) {
  130. let elem = $(this.config.elem);
  131. if (target === 'radio') {
  132. let selectValue = elem.find(`select[name="${this.config.name}"]`).val();
  133. elem.find(`input[name="${this.config.name}"][value="` + selectValue + '"]').prop('checked', true);
  134. form.render('radio');
  135. } else {
  136. let radioValue = elem.find(`input[name="${this.config.name}"]:checked`).val();
  137. elem.find(`select[name="${this.config.name}"]`).val(radioValue);
  138. form.render('select');
  139. }
  140. },
  141. // 获取当前值
  142. getValue: function () {
  143. return $(this.config.elem).find(`input[name="${this.config.name}"]:checked`).val();
  144. },
  145. // 设置值
  146. setValue: function (value) {
  147. let elem = $(this.config.elem);
  148. elem.find(`input[name="${this.config.name}"][value="${value}"]`).prop('checked', true);
  149. elem.find(`select[name="${this.config.name}"]`).val(value);
  150. form.render();
  151. },
  152. };
  153. // 暴露接口
  154. exports('switchSelect', function (options) {
  155. return new SwitchSelect(options);
  156. });
  157. });
  158. let currentScriptPath = document.currentScript.src;
  159. const urlObj = new URL(currentScriptPath);
  160. layui.link(urlObj.pathname.replace('switchSelect.js', 'switchSelect.css'));