352 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			352 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
// 图书列表页面脚本
 | 
						||
$(document).ready(function() {
 | 
						||
  // 自定义下拉列表处理
 | 
						||
  const filterHeaders = document.querySelectorAll('.filter-header');
 | 
						||
 | 
						||
  filterHeaders.forEach(header => {
 | 
						||
    header.addEventListener('click', function() {
 | 
						||
      // 切换当前下拉列表
 | 
						||
      const dropdown = this.nextElementSibling;
 | 
						||
      const isOpen = dropdown.classList.contains('show');
 | 
						||
 | 
						||
      // 关闭所有下拉列表
 | 
						||
      document.querySelectorAll('.dropdown-options').forEach(el => {
 | 
						||
        el.classList.remove('show');
 | 
						||
      });
 | 
						||
      document.querySelectorAll('.filter-header').forEach(el => {
 | 
						||
        el.classList.remove('open');
 | 
						||
      });
 | 
						||
 | 
						||
      // 如果当前不是打开状态,则打开它
 | 
						||
      if(!isOpen) {
 | 
						||
        dropdown.classList.add('show');
 | 
						||
        this.classList.add('open');
 | 
						||
      }
 | 
						||
    });
 | 
						||
  });
 | 
						||
 | 
						||
  // 点击选项时更新并提交表单
 | 
						||
  const optionItems = document.querySelectorAll('.option-item');
 | 
						||
  optionItems.forEach(item => {
 | 
						||
    item.addEventListener('click', function() {
 | 
						||
      const container = this.closest('.custom-select-container');
 | 
						||
      const header = container.querySelector('.filter-header .filter-title');
 | 
						||
      const dropdown = this.closest('.dropdown-options');
 | 
						||
      const hiddenInput = container.querySelector('input[type="hidden"]');
 | 
						||
 | 
						||
      // 移除之前的选中项
 | 
						||
      dropdown.querySelectorAll('.option-item').forEach(opt => {
 | 
						||
        opt.classList.remove('selected');
 | 
						||
      });
 | 
						||
 | 
						||
      // 设置新的选中项
 | 
						||
      this.classList.add('selected');
 | 
						||
 | 
						||
      // 更新隐藏输入值
 | 
						||
      const value = this.getAttribute('data-value');
 | 
						||
      hiddenInput.value = value;
 | 
						||
 | 
						||
      // 更新显示的文本和图标
 | 
						||
      const icon = this.querySelector('i').cloneNode(true);
 | 
						||
      const text = this.querySelector('span').textContent;
 | 
						||
 | 
						||
      header.innerHTML = '';
 | 
						||
      header.appendChild(icon);
 | 
						||
      const span = document.createElement('span');
 | 
						||
      span.textContent = text;
 | 
						||
      header.appendChild(span);
 | 
						||
 | 
						||
      // 关闭下拉列表
 | 
						||
      dropdown.classList.remove('show');
 | 
						||
      container.querySelector('.filter-header').classList.remove('open');
 | 
						||
 | 
						||
      // 提交表单
 | 
						||
      document.getElementById('filter-form').submit();
 | 
						||
    });
 | 
						||
  });
 | 
						||
 | 
						||
  // 点击页面其他地方关闭下拉列表
 | 
						||
  document.addEventListener('click', function(e) {
 | 
						||
    if(!e.target.closest('.custom-select-container')) {
 | 
						||
      document.querySelectorAll('.dropdown-options').forEach(el => {
 | 
						||
        el.classList.remove('show');
 | 
						||
      });
 | 
						||
      document.querySelectorAll('.filter-header').forEach(el => {
 | 
						||
        el.classList.remove('open');
 | 
						||
      });
 | 
						||
    }
 | 
						||
  });
 | 
						||
 | 
						||
  // 处理删除图书
 | 
						||
  let bookIdToDelete = null;
 | 
						||
 | 
						||
  $('.delete-book').click(function(e) {
 | 
						||
    e.preventDefault();
 | 
						||
    bookIdToDelete = $(this).data('id');
 | 
						||
    const bookTitle = $(this).data('title');
 | 
						||
    $('#deleteBookTitle').text(bookTitle);
 | 
						||
    $('#deleteModal').modal('show');
 | 
						||
  });
 | 
						||
 | 
						||
  $('#confirmDelete').click(function() {
 | 
						||
    if (!bookIdToDelete) return;
 | 
						||
 | 
						||
    $.ajax({
 | 
						||
      url: `/book/delete/${bookIdToDelete}`,
 | 
						||
      type: 'POST',
 | 
						||
      success: function(response) {
 | 
						||
        if (response.success) {
 | 
						||
          $('#deleteModal').modal('hide');
 | 
						||
          // 显示成功消息
 | 
						||
          showNotification(response.message, 'success');
 | 
						||
          // 移除图书卡片
 | 
						||
          $(`.book-card[data-id="${bookIdToDelete}"]`).fadeOut(300, function() {
 | 
						||
            $(this).remove();
 | 
						||
          });
 | 
						||
          setTimeout(() => {
 | 
						||
            if ($('.book-card').length === 0) {
 | 
						||
              location.reload(); // 如果没有图书了,刷新页面显示"无图书"提示
 | 
						||
            }
 | 
						||
          }, 500);
 | 
						||
        } else {
 | 
						||
          $('#deleteModal').modal('hide');
 | 
						||
          showNotification(response.message, 'error');
 | 
						||
        }
 | 
						||
      },
 | 
						||
      error: function() {
 | 
						||
        $('#deleteModal').modal('hide');
 | 
						||
        showNotification('删除操作失败,请稍后重试', 'error');
 | 
						||
      }
 | 
						||
    });
 | 
						||
  });
 | 
						||
 | 
						||
  // 处理借阅图书
 | 
						||
  $('.borrow-book').click(function(e) {
 | 
						||
    e.preventDefault();
 | 
						||
    const bookId = $(this).data('id');
 | 
						||
 | 
						||
    $.ajax({
 | 
						||
      url: `/borrow/add/${bookId}`,
 | 
						||
      type: 'POST',
 | 
						||
      success: function(response) {
 | 
						||
        if (response.success) {
 | 
						||
          showNotification(response.message, 'success');
 | 
						||
          // 可以更新UI显示,比如更新库存或禁用借阅按钮
 | 
						||
          setTimeout(() => {
 | 
						||
            location.reload();
 | 
						||
          }, 800);
 | 
						||
        } else {
 | 
						||
          showNotification(response.message, 'error');
 | 
						||
        }
 | 
						||
      },
 | 
						||
      error: function() {
 | 
						||
        showNotification('借阅操作失败,请稍后重试', 'error');
 | 
						||
      }
 | 
						||
    });
 | 
						||
  });
 | 
						||
 | 
						||
  // 显示通知
 | 
						||
  function showNotification(message, type) {
 | 
						||
    // 移除可能存在的旧通知
 | 
						||
    $('.notification-alert').remove();
 | 
						||
 | 
						||
    const alertClass = type === 'success' ? 'notification-success' : 'notification-error';
 | 
						||
    const iconClass = type === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle';
 | 
						||
 | 
						||
    const notification = `
 | 
						||
      <div class="notification-alert ${alertClass}">
 | 
						||
        <div class="notification-icon">
 | 
						||
          <i class="fas ${iconClass}"></i>
 | 
						||
        </div>
 | 
						||
        <div class="notification-message">${message}</div>
 | 
						||
        <button class="notification-close">
 | 
						||
          <i class="fas fa-times"></i>
 | 
						||
        </button>
 | 
						||
      </div>
 | 
						||
    `;
 | 
						||
 | 
						||
    $('body').append(notification);
 | 
						||
 | 
						||
    // 显示通知
 | 
						||
    setTimeout(() => {
 | 
						||
      $('.notification-alert').addClass('show');
 | 
						||
    }, 10);
 | 
						||
 | 
						||
    // 通知自动关闭
 | 
						||
    setTimeout(() => {
 | 
						||
      $('.notification-alert').removeClass('show');
 | 
						||
      setTimeout(() => {
 | 
						||
        $('.notification-alert').remove();
 | 
						||
      }, 300);
 | 
						||
    }, 4000);
 | 
						||
 | 
						||
    // 点击关闭按钮
 | 
						||
    $('.notification-close').click(function() {
 | 
						||
      $(this).closest('.notification-alert').removeClass('show');
 | 
						||
      setTimeout(() => {
 | 
						||
        $(this).closest('.notification-alert').remove();
 | 
						||
      }, 300);
 | 
						||
    });
 | 
						||
  }
 | 
						||
 | 
						||
  // 添加通知样式
 | 
						||
  const notificationCSS = `
 | 
						||
    .notification-alert {
 | 
						||
      position: fixed;
 | 
						||
      top: 20px;
 | 
						||
      right: 20px;
 | 
						||
      min-width: 280px;
 | 
						||
      max-width: 350px;
 | 
						||
      background-color: white;
 | 
						||
      border-radius: 8px;
 | 
						||
      box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);
 | 
						||
      display: flex;
 | 
						||
      align-items: center;
 | 
						||
      padding: 15px;
 | 
						||
      transform: translateX(calc(100% + 20px));
 | 
						||
      transition: transform 0.3s ease;
 | 
						||
      z-index: 9999;
 | 
						||
    }
 | 
						||
    
 | 
						||
    .notification-alert.show {
 | 
						||
      transform: translateX(0);
 | 
						||
    }
 | 
						||
    
 | 
						||
    .notification-success {
 | 
						||
      border-left: 4px solid var(--success-color);
 | 
						||
    }
 | 
						||
    
 | 
						||
    .notification-error {
 | 
						||
      border-left: 4px solid var(--danger-color);
 | 
						||
    }
 | 
						||
    
 | 
						||
    .notification-icon {
 | 
						||
      margin-right: 15px;
 | 
						||
      font-size: 24px;
 | 
						||
    }
 | 
						||
    
 | 
						||
    .notification-success .notification-icon {
 | 
						||
      color: var(--success-color);
 | 
						||
    }
 | 
						||
    
 | 
						||
    .notification-error .notification-icon {
 | 
						||
      color: var(--danger-color);
 | 
						||
    }
 | 
						||
    
 | 
						||
    .notification-message {
 | 
						||
      flex: 1;
 | 
						||
      font-size: 0.95rem;
 | 
						||
      color: var(--text-color);
 | 
						||
    }
 | 
						||
    
 | 
						||
    .notification-close {
 | 
						||
      background: none;
 | 
						||
      border: none;
 | 
						||
      color: var(--text-lighter);
 | 
						||
      cursor: pointer;
 | 
						||
      padding: 5px;
 | 
						||
      margin-left: 10px;
 | 
						||
      font-size: 0.8rem;
 | 
						||
    }
 | 
						||
    
 | 
						||
    .notification-close:hover {
 | 
						||
      color: var(--text-color);
 | 
						||
    }
 | 
						||
    
 | 
						||
    @media (max-width: 576px) {
 | 
						||
      .notification-alert {
 | 
						||
        top: auto;
 | 
						||
        bottom: 20px;
 | 
						||
        left: 20px;
 | 
						||
        right: 20px;
 | 
						||
        min-width: auto;
 | 
						||
        max-width: none;
 | 
						||
        transform: translateY(calc(100% + 20px));
 | 
						||
      }
 | 
						||
      
 | 
						||
      .notification-alert.show {
 | 
						||
        transform: translateY(0);
 | 
						||
      }
 | 
						||
    }
 | 
						||
  `;
 | 
						||
 | 
						||
  // 将通知样式添加到头部
 | 
						||
  $('<style>').text(notificationCSS).appendTo('head');
 | 
						||
 | 
						||
  // 修复图书卡片布局的高度问题
 | 
						||
  function adjustCardHeights() {
 | 
						||
    // 重置所有卡片高度
 | 
						||
    $('.book-card').css('height', 'auto');
 | 
						||
 | 
						||
    // 在大屏幕上应用等高布局
 | 
						||
    if (window.innerWidth >= 768) {
 | 
						||
      // 分组按行
 | 
						||
      const rows = {};
 | 
						||
      $('.book-card').each(function() {
 | 
						||
        const offsetTop = $(this).offset().top;
 | 
						||
        if (!rows[offsetTop]) {
 | 
						||
          rows[offsetTop] = [];
 | 
						||
        }
 | 
						||
        rows[offsetTop].push($(this));
 | 
						||
      });
 | 
						||
 | 
						||
      // 为每行设置相同高度
 | 
						||
      Object.keys(rows).forEach(offsetTop => {
 | 
						||
        const cards = rows[offsetTop];
 | 
						||
        let maxHeight = 0;
 | 
						||
 | 
						||
        // 找出最大高度
 | 
						||
        cards.forEach(card => {
 | 
						||
          const height = card.outerHeight();
 | 
						||
          if (height > maxHeight) {
 | 
						||
            maxHeight = height;
 | 
						||
          }
 | 
						||
        });
 | 
						||
 | 
						||
        // 应用最大高度
 | 
						||
        cards.forEach(card => {
 | 
						||
          card.css('height', maxHeight + 'px');
 | 
						||
        });
 | 
						||
      });
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  // 初始调整高度
 | 
						||
  $(window).on('load', adjustCardHeights);
 | 
						||
 | 
						||
  // 窗口大小变化时调整高度
 | 
						||
  $(window).on('resize', adjustCardHeights);
 | 
						||
 | 
						||
  // 为封面图片添加加载错误处理
 | 
						||
  $('.book-cover img').on('error', function() {
 | 
						||
    const $this = $(this);
 | 
						||
    const bookTitle = $this.attr('alt') || '图书';
 | 
						||
    const $cover = $this.closest('.book-cover');
 | 
						||
 | 
						||
    // 替换为无封面显示
 | 
						||
    $cover.html(`
 | 
						||
      <div class="no-cover">
 | 
						||
        <i class="fas fa-book"></i>
 | 
						||
        <span>无封面</span>
 | 
						||
      </div>
 | 
						||
      <div class="cover-title-bar">${bookTitle}</div>
 | 
						||
    `);
 | 
						||
  });
 | 
						||
 | 
						||
  // 添加初始动画效果
 | 
						||
  $('.book-card').each(function(index) {
 | 
						||
    $(this).css({
 | 
						||
      'opacity': '0',
 | 
						||
      'transform': 'translateY(20px)'
 | 
						||
    });
 | 
						||
 | 
						||
    setTimeout(() => {
 | 
						||
      $(this).css({
 | 
						||
        'opacity': '1',
 | 
						||
        'transform': 'translateY(0)',
 | 
						||
        'transition': 'opacity 0.5s ease, transform 0.5s ease'
 | 
						||
      });
 | 
						||
    }, 50 * index);
 | 
						||
  });
 | 
						||
});
 |