tcsModal.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /**
  2. * TCS模态框组件
  3. * 用于封装模态框相关的逻辑,提供统一的接口
  4. */
  5. class TcsModal {
  6. /**
  7. * 构造函数
  8. * @param {Object} options - 配置选项
  9. * @param {string} options.modalId - 模态框的ID
  10. * @param {string} [options.confirmBtnId] - 确认按钮的ID
  11. * @param {string} [options.formId] - 表单的ID(如果有)
  12. * @param {Function} [options.onConfirm] - 确认按钮点击时的回调函数
  13. * @param {Function} [options.onShow] - 模态框显示时的回调函数
  14. * @param {Function} [options.onHide] - 模态框隐藏时的回调函数
  15. * @param {Function} [options.onValidate] - 表单验证的回调函数(如果有表单)
  16. */
  17. constructor(options) {
  18. this.modalId = options.modalId;
  19. this.confirmBtnId = options.confirmBtnId;
  20. this.formId = options.formId;
  21. this.onConfirm = options.onConfirm || (() => {});
  22. this.onShow = options.onShow || (() => {});
  23. this.onHide = options.onHide || (() => {});
  24. this.onValidate = options.onValidate || (() => true);
  25. this.modalElement = document.getElementById(this.modalId);
  26. this.confirmBtn = this.confirmBtnId ? document.getElementById(this.confirmBtnId) : null;
  27. this.form = this.formId ? document.getElementById(this.formId) : null;
  28. this.modalInstance = null;
  29. this.init();
  30. }
  31. /**
  32. * 初始化模态框
  33. */
  34. init() {
  35. if (!this.modalElement) {
  36. console.error(`模态框元素 #${this.modalId} 不存在`);
  37. return;
  38. }
  39. // 初始化Bootstrap模态框实例
  40. this.modalInstance = new bootstrap.Modal(this.modalElement);
  41. // 绑定确认按钮事件
  42. if (this.confirmBtn) {
  43. this.confirmBtn.addEventListener('click', this.handleConfirm.bind(this));
  44. }
  45. // 绑定模态框事件
  46. this.modalElement.addEventListener('show.bs.modal', this.handleShow.bind(this));
  47. this.modalElement.addEventListener('hidden.bs.modal', this.handleHide.bind(this));
  48. }
  49. /**
  50. * 处理确认按钮点击事件
  51. * @param {Event} event - 事件对象
  52. */
  53. handleConfirm(event) {
  54. // 如果有表单,进行表单验证
  55. if (this.form) {
  56. if (!this.form.checkValidity()) {
  57. event.preventDefault();
  58. event.stopPropagation();
  59. this.form.classList.add('was-validated');
  60. return;
  61. }
  62. // 自定义验证
  63. if (!this.onValidate()) {
  64. return;
  65. }
  66. // 获取表单数据
  67. const formData = new FormData(this.form);
  68. const data = Object.fromEntries(formData.entries());
  69. // 调用确认回调,传入表单数据
  70. this.onConfirm(data);
  71. } else {
  72. // 没有表单,直接调用确认回调
  73. this.onConfirm();
  74. }
  75. // 隐藏模态框
  76. this.hide();
  77. }
  78. /**
  79. * 处理模态框显示事件
  80. * @param {Event} event - 事件对象
  81. */
  82. handleShow(event) {
  83. // 获取触发模态框的元素(如果有)
  84. const relatedTarget = event.relatedTarget;
  85. this.onShow(relatedTarget);
  86. }
  87. /**
  88. * 处理模态框隐藏事件
  89. */
  90. handleHide() {
  91. // 如果有表单,重置表单
  92. if (this.form) {
  93. this.form.reset();
  94. this.form.classList.remove('was-validated');
  95. }
  96. this.onHide();
  97. }
  98. /**
  99. * 显示模态框
  100. */
  101. show() {
  102. this.modalInstance.show();
  103. }
  104. /**
  105. * 隐藏模态框
  106. */
  107. hide() {
  108. this.modalInstance.hide();
  109. }
  110. /**
  111. * 销毁模态框实例
  112. */
  113. destroy() {
  114. if (this.confirmBtn) {
  115. this.confirmBtn.removeEventListener('click', this.handleConfirm);
  116. }
  117. this.modalElement.removeEventListener('show.bs.modal', this.handleShow);
  118. this.modalElement.removeEventListener('hidden.bs.modal', this.handleHide);
  119. this.modalInstance.dispose();
  120. }
  121. }
  122. /**
  123. * 通知提示组件
  124. * 用于显示操作结果的通知提示
  125. */
  126. class TcsNotify {
  127. /**
  128. * 显示通知提示
  129. * @param {string} message - 通知消息
  130. * @param {string} [type='success'] - 通知类型,可选值:success, danger, warning, info, primary
  131. * @param {number} [duration=5000] - 通知显示时间(毫秒)
  132. */
  133. static show(message, type = 'success', duration = 5000) {
  134. // 定义图标映射
  135. const icons = {
  136. 'success': 'square-check',
  137. 'danger': 'circle-x',
  138. 'warning': 'alert-triangle',
  139. 'info': 'info-circle',
  140. 'primary': 'bell'
  141. };
  142. // 获取图标
  143. const icon = icons[type] || 'info-circle';
  144. // 创建通知元素
  145. const notification = document.createElement('div');
  146. notification.className = `alert alert-${type} alert-dismissible`;
  147. notification.style.paddingTop = '0.5rem';
  148. notification.style.paddingBottom = '0.5rem';
  149. // 设置通知内容
  150. notification.innerHTML = `
  151. <div class="d-flex align-items-center">
  152. <div class="d-flex align-items-center">
  153. <i class="ti ti-${icon} alert-icon me-2" style="font-size: 1.25rem;"></i>
  154. </div>
  155. <div>
  156. ${message}
  157. </div>
  158. </div>
  159. <a class="btn-close" data-bs-dismiss="alert" aria-label="close"></a>
  160. `;
  161. // 创建通知容器
  162. let notifyContainer = document.getElementById('notify-container');
  163. if (!notifyContainer) {
  164. notifyContainer = document.createElement('div');
  165. notifyContainer.id = 'notify-container';
  166. notifyContainer.className = 'position-fixed top-0 start-50 translate-middle-x p-2';
  167. notifyContainer.style.zIndex = '9999';
  168. notifyContainer.style.paddingTop = '0.5rem';
  169. notifyContainer.style.paddingBottom = '0.5rem';
  170. document.body.appendChild(notifyContainer);
  171. }
  172. // 添加到容器
  173. notifyContainer.appendChild(notification);
  174. // 指定时间后自动关闭
  175. setTimeout(() => {
  176. if (notification.parentNode) {
  177. // 使用Bootstrap的Alert API关闭
  178. const bsAlert = new bootstrap.Alert(notification);
  179. bsAlert.close();
  180. // 监听关闭完成事件
  181. notification.addEventListener('closed.bs.alert', function() {
  182. if (notification.parentNode) {
  183. notification.parentNode.removeChild(notification);
  184. }
  185. // 如果容器为空,也移除容器
  186. if (notifyContainer.children.length === 0) {
  187. notifyContainer.parentNode.removeChild(notifyContainer);
  188. }
  189. });
  190. }
  191. }, duration);
  192. }
  193. }