upgrade_book_manage
This commit is contained in:
parent
868cc88d54
commit
d86151bf6e
@ -21,6 +21,13 @@
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.category-filter-dropdown,
|
||||
.sort-dropdown,
|
||||
.order-dropdown {
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
|
||||
@keyframes bubble {
|
||||
0% {
|
||||
transform: translateY(100%) scale(0);
|
||||
@ -181,30 +188,188 @@
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
/* 现代化下拉列表样式 */
|
||||
.filter-section .custom-select-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.filter-section .filter-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 12px;
|
||||
padding: 12px 16px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
||||
border: 2px solid #f9c0d0;
|
||||
transition: all 0.3s ease;
|
||||
background-color: rgba(255, 255, 255, 0.95);
|
||||
color: #666;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.filter-section .filter-header:hover {
|
||||
border-color: #e67e9f;
|
||||
box-shadow: 0 0 0 3px rgba(230, 126, 159, 0.1);
|
||||
background-color: #fff;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.filter-section .filter-header .filter-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.filter-section .filter-header .filter-title i {
|
||||
color: #e67e9f;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.filter-section .filter-header .icon-arrow {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.filter-section .filter-header.open .icon-arrow {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.filter-section .dropdown-options {
|
||||
position: absolute;
|
||||
top: calc(100% + 8px);
|
||||
left: 0;
|
||||
right: 0;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
background-color: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);
|
||||
z-index: 9999;
|
||||
padding: 8px 0;
|
||||
display: none;
|
||||
animation: dropdownFadeIn 0.3s ease;
|
||||
border: 1px solid rgba(233, 152, 174, 0.3);
|
||||
}
|
||||
|
||||
.filter-section .dropdown-options.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@keyframes dropdownFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.filter-section .option-item {
|
||||
padding: 10px 16px;
|
||||
color: #666;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.filter-section .option-item:hover {
|
||||
background: linear-gradient(135deg, #ffeef2, #ffd9e2);
|
||||
color: #d23f6e;
|
||||
}
|
||||
|
||||
.filter-section .option-item.selected {
|
||||
background: linear-gradient(135deg, #ffeef2, #ffd9e2);
|
||||
color: #d23f6e;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.filter-section .option-item i {
|
||||
font-size: 16px;
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.filter-section .option-item.all-option {
|
||||
background-color: #f0f7ff;
|
||||
margin: 0 8px 8px 8px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.filter-section .option-item.all-option i {
|
||||
color: #4a73c7;
|
||||
}
|
||||
|
||||
/* 全局类别和选项图标 */
|
||||
.filter-section .icon-all {
|
||||
color: #4a73c7;
|
||||
}
|
||||
|
||||
.filter-section .icon-literature {
|
||||
color: #e67e9f;
|
||||
}
|
||||
|
||||
.filter-section .icon-novel {
|
||||
color: #f0ad4e;
|
||||
}
|
||||
|
||||
.filter-section .icon-essay {
|
||||
color: #56c596;
|
||||
}
|
||||
|
||||
.filter-section .icon-computer {
|
||||
color: #5bc0de;
|
||||
}
|
||||
|
||||
.filter-section .icon-programming {
|
||||
color: #9c27b0;
|
||||
}
|
||||
|
||||
.filter-section .icon-sort {
|
||||
color: #5c88da;
|
||||
}
|
||||
|
||||
.filter-section .icon-order {
|
||||
color: #e67e9f;
|
||||
}
|
||||
|
||||
/* 使搜索框和下拉列表样式保持一致 */
|
||||
.search-group .form-control {
|
||||
border: 1px solid #f9c0d0;
|
||||
border: 2px solid #f9c0d0;
|
||||
height: 46px;
|
||||
font-weight: 500;
|
||||
color: #666;
|
||||
transition: all 0.3s ease;
|
||||
border-right: none;
|
||||
border-radius: 25px 0 0 25px;
|
||||
border-radius: 12px 0 0 12px;
|
||||
padding: 10px 20px;
|
||||
height: 42px;
|
||||
font-size: 0.95rem;
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.3s;
|
||||
background-color: rgba(255, 255, 255, 0.95);
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.search-group .form-control:focus {
|
||||
outline: none;
|
||||
.search-group .form-control:hover {
|
||||
border-color: #e67e9f;
|
||||
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 0 0 3px rgba(230, 126, 159, 0.2);
|
||||
box-shadow: 0 0 0 3px rgba(230, 126, 159, 0.1);
|
||||
}
|
||||
|
||||
.search-group .form-control:focus {
|
||||
border-color: #d23f6e;
|
||||
box-shadow: 0 0 0 3px rgba(230, 126, 159, 0.2);
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.search-group .btn {
|
||||
border-radius: 50%;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
min-width: 42px;
|
||||
border-radius: 0 12px 12px 0;
|
||||
width: 46px;
|
||||
height: 46px;
|
||||
min-width: 46px;
|
||||
padding: 0;
|
||||
background: linear-gradient(135deg, #e67e9f 60%, #ffd3e1 100%);
|
||||
color: white;
|
||||
@ -232,28 +397,7 @@
|
||||
|
||||
.filter-group {
|
||||
flex: 1;
|
||||
min-width: 130px;
|
||||
}
|
||||
|
||||
.filter-section .form-control {
|
||||
border: 1px solid #f9c0d0;
|
||||
border-radius: 25px;
|
||||
height: 42px;
|
||||
padding: 10px 20px;
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
appearance: none;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23e67e9f' d='M6 8.825L1.175 4 2.238 2.938 6 6.7 9.763 2.937 10.825 4z'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 15px center;
|
||||
background-size: 12px;
|
||||
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.filter-section .form-control:focus {
|
||||
outline: none;
|
||||
border-color: #e67e9f;
|
||||
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 0 0 3px rgba(230, 126, 159, 0.2);
|
||||
min-width: 180px;
|
||||
}
|
||||
|
||||
/* 图书网格布局 */
|
||||
@ -263,7 +407,7 @@
|
||||
gap: 24px;
|
||||
margin-bottom: 30px;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
/*z-index: 2;*/
|
||||
}
|
||||
|
||||
/* 图书卡片样式 */
|
||||
@ -685,9 +829,17 @@
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
padding: 15px;
|
||||
margin-bottom: 25px;
|
||||
padding: 18px;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
|
||||
position: relative;
|
||||
z-index: 100; /* Higher than books-grid but lower than dropdown-options */
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
|
||||
.search-form {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
@ -702,7 +854,12 @@
|
||||
}
|
||||
|
||||
.books-grid {
|
||||
grid-template-columns: 1fr;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||
gap: 24px;
|
||||
margin-bottom: 30px;
|
||||
position: relative;
|
||||
z-index: 10; /* Lower than filter-section */
|
||||
}
|
||||
|
||||
.book-actions {
|
||||
|
||||
@ -1,41 +1,81 @@
|
||||
// 图书列表页面脚本
|
||||
$(document).ready(function() {
|
||||
// 处理分类筛选
|
||||
function setFilter(button, categoryId) {
|
||||
// 移除所有按钮的活跃状态
|
||||
$('.filter-btn').removeClass('active');
|
||||
// 为当前点击的按钮添加活跃状态
|
||||
$(button).addClass('active');
|
||||
// 设置隐藏的分类ID输入值
|
||||
$('#category_id').val(categoryId);
|
||||
// 提交表单
|
||||
$(button).closest('form').submit();
|
||||
// 自定义下拉列表处理
|
||||
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');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 处理排序方向切换
|
||||
function toggleSortDirection(button) {
|
||||
const $button = $(button);
|
||||
const isAsc = $button.hasClass('asc');
|
||||
// 点击选项时更新并提交表单
|
||||
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"]');
|
||||
|
||||
// 切换方向类
|
||||
$button.toggleClass('asc desc');
|
||||
// 移除之前的选中项
|
||||
dropdown.querySelectorAll('.option-item').forEach(opt => {
|
||||
opt.classList.remove('selected');
|
||||
});
|
||||
|
||||
// 更新图标
|
||||
if (isAsc) {
|
||||
$button.find('i').removeClass('fa-sort-amount-up').addClass('fa-sort-amount-down');
|
||||
$('#sort_order').val('desc');
|
||||
} else {
|
||||
$button.find('i').removeClass('fa-sort-amount-down').addClass('fa-sort-amount-up');
|
||||
$('#sort_order').val('asc');
|
||||
}
|
||||
// 设置新的选中项
|
||||
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');
|
||||
|
||||
// 提交表单
|
||||
$button.closest('form').submit();
|
||||
}
|
||||
document.getElementById('filter-form').submit();
|
||||
});
|
||||
});
|
||||
|
||||
// 将函数暴露到全局作用域
|
||||
window.setFilter = setFilter;
|
||||
window.toggleSortDirection = toggleSortDirection;
|
||||
// 点击页面其他地方关闭下拉列表
|
||||
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;
|
||||
@ -278,16 +318,18 @@ $(document).ready(function() {
|
||||
$(window).on('resize', adjustCardHeights);
|
||||
|
||||
// 为封面图片添加加载错误处理
|
||||
$('.book-cover').on('error', function() {
|
||||
$('.book-cover img').on('error', function() {
|
||||
const $this = $(this);
|
||||
const title = $this.attr('alt') || '图书';
|
||||
const bookTitle = $this.attr('alt') || '图书';
|
||||
const $cover = $this.closest('.book-cover');
|
||||
|
||||
// 替换为默认封面
|
||||
$this.replaceWith(`
|
||||
<div class="default-cover">
|
||||
// 替换为无封面显示
|
||||
$cover.html(`
|
||||
<div class="no-cover">
|
||||
<i class="fas fa-book"></i>
|
||||
<span class="default-cover-text">${title.charAt(0)}</span>
|
||||
<span>无封面</span>
|
||||
</div>
|
||||
<div class="cover-title-bar">${bookTitle}</div>
|
||||
`);
|
||||
});
|
||||
|
||||
|
||||
@ -8,6 +8,10 @@
|
||||
|
||||
{% block content %}
|
||||
<div class="book-list-container">
|
||||
<!-- 添加泡泡动画元素 -->
|
||||
{% for i in range(15) %}
|
||||
<div class="bubble"></div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="page-header">
|
||||
<h1>图书管理</h1>
|
||||
@ -31,7 +35,7 @@
|
||||
</div>
|
||||
|
||||
<div class="filter-section">
|
||||
<form method="GET" action="{{ url_for('book.book_list') }}" class="search-form">
|
||||
<form method="GET" action="{{ url_for('book.book_list') }}" class="search-form" id="filter-form">
|
||||
<div class="search-row">
|
||||
<div class="form-group search-group">
|
||||
<input type="text" name="search" class="form-control" placeholder="搜索书名/作者/ISBN" value="{{ search }}">
|
||||
@ -41,29 +45,89 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-row">
|
||||
<div class="form-group filter-group">
|
||||
<select name="category_id" class="form-control" onchange="this.form.submit()">
|
||||
<option value="">全部分类</option>
|
||||
<div class="filter-group">
|
||||
<div class="custom-select-container" id="category-select">
|
||||
<div class="filter-header">
|
||||
<div class="filter-title">
|
||||
<i class="fas fa-tags icon-literature"></i>
|
||||
<span>{% if category_id %}{% for category in categories %}{% if category.id == category_id %}{{ category.name }}{% endif %}{% endfor %}{% else %}全部分类{% endif %}</span>
|
||||
</div>
|
||||
<i class="fas fa-chevron-down icon-arrow"></i>
|
||||
</div>
|
||||
<div class="dropdown-options">
|
||||
<div class="option-item all-option {% if not category_id %}selected{% endif %}" data-value="">
|
||||
<i class="fas fa-globe icon-all"></i>
|
||||
<span>全部分类</span>
|
||||
</div>
|
||||
{% for category in categories %}
|
||||
<option value="{{ category.id }}" {% if category_id == category.id %}selected{% endif %}>
|
||||
{{ category.name }}
|
||||
</option>
|
||||
<div class="option-item {% if category_id == category.id %}selected{% endif %}" data-value="{{ category.id }}">
|
||||
<i class="fas fa-book icon-literature"></i>
|
||||
<span>{{ category.name }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group filter-group">
|
||||
<select name="sort" class="form-control" onchange="this.form.submit()">
|
||||
<option value="id" {% if sort == 'id' %}selected{% endif %}>默认排序</option>
|
||||
<option value="created_at" {% if sort == 'created_at' %}selected{% endif %}>入库时间</option>
|
||||
<option value="title" {% if sort == 'title' %}selected{% endif %}>书名</option>
|
||||
<option value="stock" {% if sort == 'stock' %}selected{% endif %}>库存</option>
|
||||
</select>
|
||||
<input type="hidden" name="category_id" value="{{ category_id }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="filter-group">
|
||||
<div class="custom-select-container" id="sort-select">
|
||||
<div class="filter-header">
|
||||
<div class="filter-title">
|
||||
<i class="fas fa-sort-amount-down icon-sort"></i>
|
||||
<span>
|
||||
{% if sort == 'id' %}默认排序
|
||||
{% elif sort == 'created_at' %}入库时间
|
||||
{% elif sort == 'title' %}书名
|
||||
{% elif sort == 'stock' %}库存
|
||||
{% else %}默认排序{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
<i class="fas fa-chevron-down icon-arrow"></i>
|
||||
</div>
|
||||
<div class="dropdown-options">
|
||||
<div class="option-item {% if sort == 'id' %}selected{% endif %}" data-value="id">
|
||||
<i class="fas fa-sort-numeric-down"></i>
|
||||
<span>默认排序</span>
|
||||
</div>
|
||||
<div class="option-item {% if sort == 'created_at' %}selected{% endif %}" data-value="created_at">
|
||||
<i class="fas fa-calendar-alt"></i>
|
||||
<span>入库时间</span>
|
||||
</div>
|
||||
<div class="option-item {% if sort == 'title' %}selected{% endif %}" data-value="title">
|
||||
<i class="fas fa-font"></i>
|
||||
<span>书名</span>
|
||||
</div>
|
||||
<div class="option-item {% if sort == 'stock' %}selected{% endif %}" data-value="stock">
|
||||
<i class="fas fa-warehouse"></i>
|
||||
<span>库存</span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="sort" value="{{ sort }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="filter-group">
|
||||
<div class="custom-select-container" id="order-select">
|
||||
<div class="filter-header">
|
||||
<div class="filter-title">
|
||||
<i class="fas fa-{% if order == 'asc' %}arrow-up{% else %}arrow-down{% endif %} icon-order"></i>
|
||||
<span>{% if order == 'asc' %}升序{% else %}降序{% endif %}</span>
|
||||
</div>
|
||||
<i class="fas fa-chevron-down icon-arrow"></i>
|
||||
</div>
|
||||
<div class="dropdown-options">
|
||||
<div class="option-item {% if order == 'desc' %}selected{% endif %}" data-value="desc">
|
||||
<i class="fas fa-arrow-down"></i>
|
||||
<span>降序</span>
|
||||
</div>
|
||||
<div class="option-item {% if order == 'asc' %}selected{% endif %}" data-value="asc">
|
||||
<i class="fas fa-arrow-up"></i>
|
||||
<span>升序</span>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="order" value="{{ order }}">
|
||||
</div>
|
||||
<div class="form-group filter-group">
|
||||
<select name="order" class="form-control" onchange="this.form.submit()">
|
||||
<option value="desc" {% if order == 'desc' %}selected{% endif %}>降序</option>
|
||||
<option value="asc" {% if order == 'asc' %}selected{% endif %}>升序</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -205,4 +269,3 @@
|
||||
<script src="{{ url_for('static', filename='js/book-list.js') }}"></script>
|
||||
{{ super() }}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user