314 lines
13 KiB
HTML
314 lines
13 KiB
HTML
{% extends 'base.html' %}
|
|
|
|
{% block title %}图书分类管理 - 图书管理系统{% endblock %}
|
|
|
|
{% block head %}
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/categories.css') }}">
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="categories-container">
|
|
<div class="page-header">
|
|
<h1>图书分类管理</h1>
|
|
<a href="{{ url_for('book.book_list') }}" class="btn btn-secondary">
|
|
<i class="fas fa-arrow-left"></i> 返回图书列表
|
|
</a>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
添加新分类
|
|
</div>
|
|
<div class="card-body">
|
|
<form id="categoryForm">
|
|
<div class="form-group">
|
|
<label for="categoryName">分类名称</label>
|
|
<input type="text" class="form-control" id="categoryName" name="name" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="parentCategory">父级分类</label>
|
|
<select class="form-control" id="parentCategory" name="parent_id">
|
|
<option value="">无 (顶级分类)</option>
|
|
{% for category in categories %}
|
|
<option value="{{ category.id }}">{{ category.name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="categorySort">排序</label>
|
|
<input type="number" class="form-control" id="categorySort" name="sort" value="0" min="0">
|
|
</div>
|
|
<button type="submit" class="btn btn-primary btn-block">
|
|
<i class="fas fa-plus"></i> 添加分类
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-8">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
分类列表
|
|
</div>
|
|
<div class="card-body">
|
|
{% if categories %}
|
|
<table class="table table-hover category-table">
|
|
<thead>
|
|
<tr>
|
|
<th width="5%">ID</th>
|
|
<th width="40%">分类名称</th>
|
|
<th width="20%">父级分类</th>
|
|
<th width="10%">排序</th>
|
|
<th width="25%">操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for category in categories %}
|
|
<tr data-id="{{ category.id }}">
|
|
<td>{{ category.id }}</td>
|
|
<td>{{ category.name }}</td>
|
|
<td>
|
|
{% if category.parent %}
|
|
{{ category.parent.name }}
|
|
{% else %}
|
|
<span class="text-muted">无</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>{{ category.sort }}</td>
|
|
<td>
|
|
<button class="btn btn-sm btn-primary edit-category" data-id="{{ category.id }}"
|
|
data-name="{{ category.name }}"
|
|
data-parent="{{ category.parent_id or '' }}"
|
|
data-sort="{{ category.sort }}">
|
|
<i class="fas fa-edit"></i> 编辑
|
|
</button>
|
|
<button class="btn btn-sm btn-danger delete-category" data-id="{{ category.id }}" data-name="{{ category.name }}">
|
|
<i class="fas fa-trash"></i> 删除
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% else %}
|
|
<div class="no-categories">
|
|
<i class="fas fa-exclamation-circle"></i>
|
|
<p>暂无分类数据</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 编辑分类模态框 -->
|
|
<div class="modal fade" id="editCategoryModal" tabindex="-1" role="dialog" aria-labelledby="editCategoryModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="editCategoryModalLabel">编辑分类</h5>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<form id="editCategoryForm">
|
|
<div class="modal-body">
|
|
<input type="hidden" id="editCategoryId">
|
|
<div class="form-group">
|
|
<label for="editCategoryName">分类名称</label>
|
|
<input type="text" class="form-control" id="editCategoryName" name="name" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="editParentCategory">父级分类</label>
|
|
<select class="form-control" id="editParentCategory" name="parent_id">
|
|
<option value="">无 (顶级分类)</option>
|
|
{% for category in categories %}
|
|
<option value="{{ category.id }}">{{ category.name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="editCategorySort">排序</label>
|
|
<input type="number" class="form-control" id="editCategorySort" name="sort" value="0" min="0">
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
|
|
<button type="submit" class="btn btn-primary">保存修改</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 删除确认模态框 -->
|
|
<div class="modal fade" id="deleteCategoryModal" tabindex="-1" role="dialog" aria-labelledby="deleteCategoryModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="deleteCategoryModalLabel">确认删除</h5>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>您确定要删除分类 "<span id="deleteCategoryName"></span>" 吗?</p>
|
|
<p class="text-danger">注意: 如果该分类下有图书或子分类,将无法删除!</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
|
|
<button type="button" class="btn btn-danger" id="confirmDeleteCategory">确认删除</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script>
|
|
$(document).ready(function() {
|
|
// 添加分类
|
|
$('#categoryForm').submit(function(e) {
|
|
e.preventDefault();
|
|
|
|
const formData = {
|
|
name: $('#categoryName').val(),
|
|
parent_id: $('#parentCategory').val(),
|
|
sort: $('#categorySort').val()
|
|
};
|
|
|
|
$.ajax({
|
|
url: '{{ url_for("book.add_category") }}',
|
|
type: 'POST',
|
|
data: formData,
|
|
success: function(response) {
|
|
if (response.success) {
|
|
showNotification(response.message, 'success');
|
|
setTimeout(function() {
|
|
location.reload();
|
|
}, 1000);
|
|
} else {
|
|
showNotification(response.message, 'error');
|
|
}
|
|
},
|
|
error: function() {
|
|
showNotification('操作失败,请稍后重试', 'error');
|
|
}
|
|
});
|
|
});
|
|
|
|
// 打开编辑模态框
|
|
$('.edit-category').click(function() {
|
|
const id = $(this).data('id');
|
|
const name = $(this).data('name');
|
|
const parentId = $(this).data('parent');
|
|
const sort = $(this).data('sort');
|
|
|
|
$('#editCategoryId').val(id);
|
|
$('#editCategoryName').val(name);
|
|
$('#editParentCategory').val(parentId);
|
|
$('#editCategorySort').val(sort);
|
|
|
|
// 禁用选择自己作为父级
|
|
$('#editParentCategory option').removeAttr('disabled');
|
|
$(`#editParentCategory option[value="${id}"]`).attr('disabled', 'disabled');
|
|
|
|
$('#editCategoryModal').modal('show');
|
|
});
|
|
|
|
// 提交编辑表单
|
|
$('#editCategoryForm').submit(function(e) {
|
|
e.preventDefault();
|
|
|
|
const id = $('#editCategoryId').val();
|
|
const formData = {
|
|
name: $('#editCategoryName').val(),
|
|
parent_id: $('#editParentCategory').val(),
|
|
sort: $('#editCategorySort').val()
|
|
};
|
|
|
|
$.ajax({
|
|
url: `/book/categories/edit/${id}`,
|
|
type: 'POST',
|
|
data: formData,
|
|
success: function(response) {
|
|
if (response.success) {
|
|
$('#editCategoryModal').modal('hide');
|
|
showNotification(response.message, 'success');
|
|
setTimeout(function() {
|
|
location.reload();
|
|
}, 1000);
|
|
} else {
|
|
showNotification(response.message, 'error');
|
|
}
|
|
},
|
|
error: function() {
|
|
showNotification('操作失败,请稍后重试', 'error');
|
|
}
|
|
});
|
|
});
|
|
|
|
// 打开删除确认框
|
|
$('.delete-category').click(function() {
|
|
const id = $(this).data('id');
|
|
const name = $(this).data('name');
|
|
|
|
$('#deleteCategoryName').text(name);
|
|
$('#confirmDeleteCategory').data('id', id);
|
|
|
|
$('#deleteCategoryModal').modal('show');
|
|
});
|
|
|
|
// 确认删除
|
|
$('#confirmDeleteCategory').click(function() {
|
|
const id = $(this).data('id');
|
|
|
|
$.ajax({
|
|
url: `/book/categories/delete/${id}`,
|
|
type: 'POST',
|
|
success: function(response) {
|
|
$('#deleteCategoryModal').modal('hide');
|
|
|
|
if (response.success) {
|
|
showNotification(response.message, 'success');
|
|
setTimeout(function() {
|
|
location.reload();
|
|
}, 1000);
|
|
} else {
|
|
showNotification(response.message, 'error');
|
|
}
|
|
},
|
|
error: function() {
|
|
showNotification('操作失败,请稍后重试', 'error');
|
|
}
|
|
});
|
|
});
|
|
|
|
// 显示通知
|
|
function showNotification(message, type) {
|
|
const alertClass = type === 'success' ? 'alert-success' : 'alert-danger';
|
|
const alert = `
|
|
<div class="alert ${alertClass} alert-dismissible fade show notification-alert" role="alert">
|
|
${message}
|
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
`;
|
|
|
|
$('body').append(alert);
|
|
|
|
// 5秒后自动关闭
|
|
setTimeout(() => {
|
|
$('.notification-alert').alert('close');
|
|
}, 5000);
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %}
|
|
|