图书馆管理系统(三)基于jquery、ajax

news2024/12/20 8:51:08

任务3.4 借书还书页面

任务描述

这部分主要是制作借书还书的界面,这里我分别制作了两个网页分别用来借书和还书。此页面,也是通过获取books.txt内容然后添加到表格中,但是借还的操作没有添加到后端中去,只是一个简单的前端操作。

任务实施

3.4.1 借还的页面搭建

因为两者的整体框架是一样的不一样的点只有在借还操作这一部分是不同的,所以放在一块进行。

这里为借书操作为例:

整体布局就是左面导航栏,右边为主体部分内容

主体内容部分:

.main 包含一个表格,表格的头部定义了七个列:书名、作者、出版社、价格、内容摘要、借阅状态、操作

<tbody> 部分暂时为空,稍后将通过 JavaScript 动态填充数据。

导航栏部分:有三个导航链接:

“我的空间”:链接到用户个人页面。

“图书借阅”:当前所在页面。

“图书还回”:链接到图书还回的页面。

全部代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./js/jQuery.js"></script>
    <link rel="stylesheet" href="./css/borrow.css">
</head>
<style>

</style>

<body>
    <div class="content">
        <div class="nav">
            <div class="nav-header">
                <img src="./img/user1.png" alt="">
                <h3>用户系统</h3>
            </div>
            <div class="nav-menu">
                <ul>
                    <li><a href="user.html">我的空间</a></li>
                    <li><a href="#">图书借阅</a></li>
                    <li><a href="repaid.html">图书还回</a></li>
                </ul>
            </div>
        </div>
        <div class="main">
            <table>
                <thead>
                    <tr>
                        <th>书名</th>
                        <th>作者</th>
                        <th>出版社</th>
                        <th>价格</th>
                        <th>内容摘要</th>
                        <th>借阅状态</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>

                </tbody>
            </table>
        </div>
    </div>
</body>
<script src="./js/borrow.js"></script>
</html>
而还书的部分只有这部分是不一样的
            <div class="nav-menu">
                <ul>
                    <li><a href="user.html">我的空间</a></li>
                    <li><a href="borrow.html">图书借阅</a></li>
                    <li><a href="#">图书还回</a></li>
                </ul>
            </div>
3.4.2 页面样式设置

这里样式设置部分不多说,还是以借书为例,全部代码:

*{
    margin: 0;
    padding: 0;
}
.nav {
    background-color: #2f2f2f;
    width: 20%;
    height: 100vh;
    float: left;
}
.nav-header {
    height: 6rem;
    display: flex;
}
.nav-header img {
    width: 6rem;
    height: 6rem;
    margin: 1rem 2rem;
}
.nav-header h3 {
    color: #fff;
    font-size: 2rem;
    margin-top: 1rem;
    text-align: center;
    line-height: 6rem;
}
.nav-menu {
    height: 80%;
}
.nav-menu ul {
    list-style: none;
    margin-top: 2rem;
}
.nav-menu ul li {
    margin-bottom: 1rem;
    text-indent: 2rem;
}
.nav-menu ul :hover{
    opacity: 0.9;
}
.nav-menu ul li a {
    color: #fff;
    text-decoration: none;
    font-size: 1.5rem;
} 
.main{
    background-color: cadetblue;
    border-radius: 1.5rem;
    width: 79%;
    height: 100%;
    position: absolute;
    left: 24rem;
}
.main table{
    border-collapse: collapse;
    width: 100%;
    margin-top: 2rem;
    text-align: center;
}
.main table th{
    background-color: #4CAF50;
    color: white;
    padding: 12px 16px;
}
.main table td{
    background-color: #78c37b;
    border: 1px solid #ddd;
    padding: 8px;
}
.main table td span{
    color: green;
    font-weight: bold;
}
.main table td button{
    background-color: #5fa862;
    color: white;
    border: none;
    border-radius: 5px;
    padding: 8px 16px;
    font-size: 16px;
    cursor: pointer;
}
.main table td button:hover{
    opacity: 0.8;
}

3.4.3 借还的功能实现

这里来两者这主要区别就是点击借书或还书时,转换的字体颜色不同。

点击结束或者还书的时候会有提示框并会有一个时间戳的提示。

讲解部分还是以借书为例:

首先利用 $.get 方法从 books.txt 文件中获取书籍数据。使用 $.each 遍历每一本书,并为每本书生成一行 <tr>,包括书名、作者、出版社、价格、内容摘要、借阅状态和借阅按钮。借阅状态初始设置为“未借阅”,并伴随一个“借阅”按钮。

然后使用事件代理 ($('tbody').on(...)) 来处理动态生成的借阅按钮的点击事件。

当按钮被点击时调用 getFormatDate 函数获取当前时间格式化字符串。找到当前行(使用 $(this).closest('tr')),并将 “借阅状态” 文本更改为“已借阅”,同时修改文本的颜色为红色(若是还书则初始页面字体为红色修改后则为绿色,以明确显示书籍的借阅状态。

弹出提示框显示借阅成功的信息和当前时间。

最后重要的部分就是获取当前时间的函数部分。

getFormatDate 函数用于获取当前的日期和时间,并进行格式化。

使用 Date 对象获取当前年份、月份、日期、小时和分钟,并确保它们都是两位数(例如:10、01)。

最终拼接字符串按照YYYY-MM-DD HH:mm的格式返回。

其中nowDate.getMonth():获取当前月份的索引(0-11)。

nowDate.getMonth() + 1 < 10 ? "0" + (nowDate.getMonth() + 1):检查月份是否小于 10,如果是,则在前面添加零以确保格式是“01”、“02”等。

nowDate.getDate()nowDate.getHours()nowDate.getMinutes()

与这个都是同理。

借书JS部分:

$.get('../books.txt', function (data) {
    var usres = JSON.parse(data);
    $.each(usres, function (i, book) {
        $('tbody').append(
            `
                    <tr>
                        <td>${book.bookname}</td>
                        <td>${book.author}</td>
                        <td>${book.publisher}</td>
                        <td>${book.price}</td>
                        <td>${book.content}</td>
                        <td><span class="borrow-book">未借阅</span></td>
                        <td><button class="borrow-btn">借阅</button></td>
                    </tr>
                    `
        )
    })
})
$('tbody').on('click', '.borrow-btn', function () {
    var str = getFormatDate();
    alert("借阅成功!当前时间:" + str);
    $(this).closest('tr').find('.borrow-book').text('已借阅').css('color', 'red');
})
function getFormatDate() {
    var nowDate = new Date();
    var year = nowDate.getFullYear();
    var month = nowDate.getMonth() + 1 < 10 ? "0" + (nowDate.getMonth() + 1) : nowDate.getMonth() + 1;
    var date = nowDate.getDate() < 10 ? "0" + nowDate.getDate() : nowDate.getDate();
    var hour = nowDate.getHours() < 10 ? "0" + nowDate.getHours() : nowDate.getHours();
    var minute = nowDate.getMinutes() < 10 ? "0" + nowDate.getMinutes() : nowDate.getMinutes();
    return year + "-" + month + "-" + date + " " + hour + ":" + minute;
}
还书JS部分:
$.get('../books.txt', function (data) {
    var usres = JSON.parse(data);
    $.each(usres, function (i, book) {
        $('tbody').append(
            `
                    <tr>
                        <td>${book.bookname}</td>
                        <td>${book.author}</td>
                        <td>${book.publisher}</td>
                        <td>${book.price}</td>
                        <td>${book.content}</td>
                        <td><span class="borrow-book" style="color:red">未还回</span></td>
                        <td><button class="borrow-btn">还回</button></td>
                    </tr>
                    `
        )
    })
})
$('tbody').on('click', '.borrow-btn', function () {
    var str = getFormatDate();
    alert("还书成功!当前时间:" + str);
    $(this).closest('tr').find('.borrow-book').text('已还回').css('color', 'green');

})
function getFormatDate() {
    var nowDate = new Date();
    var year = nowDate.getFullYear();
    var month = nowDate.getMonth() + 1 < 10 ? "0" + (nowDate.getMonth() + 1) : nowDate.getMonth() + 1;
    var date = nowDate.getDate() < 10 ? "0" + nowDate.getDate() : nowDate.getDate();
    var hour = nowDate.getHours() < 10 ? "0" + nowDate.getHours() : nowDate.getHours();
    var minute = nowDate.getMinutes() < 10 ? "0" + nowDate.getMinutes() : nowDate.getMinutes();
    return year + "-" + month + "-" + date + " " + hour + ":" + minute ;
}

任务3.5 图书管理功能界面

任务描述

该任务可以说是整个项目中最重要的部分,即能够连接后端进行前后端的交互,包括新增图书,编辑图书,删除图书等等。以及还有翻页功能的实现。Server.js的编写。

任务实施

3.5.1 页面框架搭建

首先想到的是需要一个表格,将我们通过ajax访问并获取txt文本,然后把获取到的内容放到表格中,所以我们可以新建一个空表格,还有新建图书和编辑图书时的表单。以及一些按钮和超链接,例如新增图书按钮,翻页部分的超链接等等。

分析后即为:

主体内容:使用<body>标签包含整个页面的主体部分。

标题:使用<h2>标签显示“图书管理系统”。

图书表格:使用<table>标签布局图书信息,表头定义了书名、作者、出版社、出版日期、页数、价格、内容摘要和操作等字段。

分页导航:有按钮和链接用于新增图书、翻页和跳转至指定页数。

新增图书表单:包含一个ID为addform的表单,用于输入新图书信息,包括书名、作者、出版社、出版日期、页数、价格和内容摘要等。

编辑图书表单:类似于新增图书的表单,供编辑现有图书信息使用。

HTML具体代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>图书信息管理</title>
    <link rel="stylesheet" href="/public/css/Admin-books.css">
    <script src="./js/jQuery.js"></script>
</head>
<body>
    <div class="container">
        <h2>图书管理系统</h2>
        <table>
            <thead>
                <tr>
                    <th>书名</th>
                    <th>作者</th>
                    <th>出版社</th>
                    <th>出版日期</th>
                    <th>页数</th>
                    <th>价格</th>
                    <th>内容摘要</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
            </tbody>
        </table>
        <div class="nav">
            <button id="add">新增图书</button>
            <span class="total-records"></span>&nbsp;&nbsp;
            <span class="current-page">第1页</span>
            <a href="#" id="first-page">第一页</a>
            <a href="#" id='prev-page'>上一页</a>
            <a href="#" id="next-page">下一页</a>
            <a href="#" id="last-page">最后一页</a>
            <span>跳转到第</span>
            <input type="text" value="1" placeholder="页码">
            <span>页</span>
            <button id="jump-to-page">确定</button>
        </div>
    </div>
    <div class="addbook">
        <h2>新增图书</h2>
        <form id="addform">
            <label for="bookname">书名:</label>
            <input type="text" id="bookname" name="bookname"><br><br>
            <label for="author">作者:</label>
            <input type="text" id="author" name="author"><br><br>
            <label for="publisher">出版社:</label>
            <input type="text" id="publisher" name="publisher"><br><br>
            <label for="publishdate">出版日期:</label>
            <input type="date" id="publishdate" name="publishdate"><br><br>
            <label for="page">页数:</label>
            <input type="text" id="page" name="page"><br><br>
            <label for="price">价格:</label>
            <input type="text" id="price" name="price"><br><br>
            <label for="content">内容摘要:</label>
            <textarea id="content" name="content"></textarea><br><br>
            <button type="submit" id="submit">提交</button><button id="close">关闭</button>
        </form>
    </div>
    <div class="editbook">
        <h2>编辑图书</h2>
        <form id="editform">
            <label for="bookname">书名:</label>
            <input type="text" id="bookname" name="bookname"><br><br>
            <label for="author">作者:</label>
            <input type="text" id="author" name="author"><br><br>
            <label for="publisher">出版社:</label>
            <input type="text" id="publisher" name="publisher"><br><br>
            <label for="publishdate">出版日期:</label>
            <input type="date" id="publishdate" name="publishdate"><br><br>
            <label for="page">页数:</label>
            <input type="text" id="page" name="page"><br><br>
            <label for="price">价格:</label>
            <input type="text" id="price" name="price"><br><br>
            <label for="content">内容摘要:</label>
            <textarea id="content" name="content"></textarea><br><br>
            <button type="submit" id="edit-submit">提交</button>
        </form>
    </div>
</body>
<script src="./js/Admin-books.js"></script>
</html>

3.5.2 页面样式设置

样式部分,主要就分为容器样式,主体内容样式,导航栏样式,链接样式等等。这里比较重要的是,我们需要先把新增图书和编辑图书隐藏掉,当我们点击相应按钮的时候再把他们分别显示出来。

CSS部分代码:

* {
    margin: 0;
    padding: 0;
}

body {
    background-image: url(../img/Admin2.png);
    background-size: cover;
}

.container {
    width: 70%;
    height: 20%;
    margin: 10rem auto;
    border: 1rem solid #adda8f;
    background-color: aliceblue;
    border-radius: 1rem;
}

h2 {
    margin: 1rem;
}

.container table {
    width: 100%;
    height: 100%;
    border: 0.1rem solid #000000;
}

.container table thead {
    background-color: #f2f2f2;
    color: #000000;
    text-align: center;
    font-size: 1.5rem;
}
.container table tbody {
    background-color: #ffffff;
    color: #000000;
    text-indent: 1rem;
    font-size: 1.2rem;
}
.nav{
    width: 80%;
    margin: 1rem auto;
}
a{
    text-decoration: none;
}
input{
    width: 7rem;
    height: 1.5rem;
}
.addbook{
    width: 40%;
    margin: 1rem auto;
    border: 1rem solid #adda8f;
    background-color: aliceblue;
    border-radius: 1rem;
    position: absolute;
    top: 10%;
    left: 25%;
    display: none;
}
.editbook{
    width: 40%;
    margin: 1rem auto;
    border: 1rem solid #adda8f;
    background-color: aliceblue;
    border-radius: 1rem;
    position: absolute;
    top: 10%;
    left: 25%;
    display: none;
}
label{
    display: inline-block;
    width: 8rem;
    text-align: right;
    margin-right: 1rem;
}
textarea{
    width: 80%;
    height: 5rem;
    resize: none;
}
button{
    width: 6rem;
    height: 2rem;
    margin-left: 1rem;
    background-color: #008CBA;
    color: #ffffff;
    border: none;
    border-radius: 0.5rem;
    cursor: pointer;
}
td {
    max-width: 150px; 
    overflow: hidden; 
    white-space: nowrap; 
    text-overflow: ellipsis; 
}

最终效果:

3.5.3 更新图书表格updateTable()函数

主要目的就是从 books.txt 的文件中获取书籍数据,并将其显示在 HTML 表格中。

这里首先定义了三个全局变量:

  1. books:一个空数组,用于存储书籍信息。
  2. currentPage:表示当前页码,初始值为 1。
  3. booksPerPage:每页显示的书籍数量,这里设置为 5。

首先先获取书籍,使用$.get() 方法从 books.txt 文件中获取数据。成功获取后,将数据解析为 JSON 对象,并将其赋值给 books 数组。最后调用 updateTable() 函数更新表格。

$.get('/books.txt', function (data) {

    var usres = JSON.parse(data);

    books = usres; // 将文件内容存入数组

    updateTable(); // 更新表格

});

下面开始进行更新表格函数的编写,首先要清空 <tbody> 的内容,以准备显示新的书籍数据。再定义了三个变量:

  1. 计算总页数:

const totalPages = Math.ceil(books.length / booksPerPage);

books.length 获取书籍的总数量(即数组长度),将其除以每页的书籍数量 booksPerPage(这里设为每页最多为5),然后使用 Math.ceil() 函数向上取整,以确保即使有一部分书籍也会增加到新的一页。

  1. 计算当前页的起始索引:

const start = (currentPage - 1) * booksPerPage;

根据当前页码 currentPage 计算当前页的起始索引。由于数组索引从 0 开始,所以需要将 currentPage 减去 1,然后乘以每页的书籍数量。这个值用于确定在 books 数组中从哪里开始取书籍。

  1. 计算当前页的结束索引:

const end = Math.min(start + booksPerPage, books.length);

start + booksPerPage 计算出当前页应显示的最后一个书籍的索引,但也可能会超过 books.length。因此,使用 Math.min() 函数确保结束索引不会超过实际书籍的数量。

再下一步,循环遍历当前页的书籍,从 start 索引开始,直到 end 索引(不包括 end),遍历当前页面应显示的书籍并获取当前书籍信息。然后再将遍历完的书籍,每部分对应的值插入到表格中。插入时使用的是jQuery 的 append() 方法。将每一本书的信息以一个新的表格行 (<tr>) 的形式添加到 <tbody> 中。每一列 (<td>) 显示书籍的不同属性。注意:其中包含两个链接,一个是 "编辑" 操作的链接,另一个是 "删除" 操作的链接。它们的 class 属性分别为 edit delete,可以用于后续的事件绑定,实现对书籍的编辑和删除功能。

let books = [];
let currentPage = 1;
const booksPerPage = 5;
// 获取books.txt文件内容
$.get('/books.txt', function (data) {
    var usres = JSON.parse(data);
    books = usres; // 将文件内容存入数组
    updateTable(); // 更新表格
});

// 更新表格函数
function updateTable() {
    $('tbody').empty();
    const totalPages = Math.ceil(books.length / booksPerPage);
    const start = (currentPage - 1) * booksPerPage;
    const end = Math.min(start + booksPerPage, books.length);

    for (let i = start; i < end; i++) {
        const book = books[i];
        $('tbody').append(`
        <tr>
            <td>${book.bookname}</td>
            <td>${book.author}</td>
            <td>${book.publisher}</td>
            <td>${book.publishdate}</td>
            <td>${book.page}</td>
            <td>${book.price}</td>
            <td>${book.content}</td>
            <td>
                <a href="#" class='edit'>编辑</a>
                <a href="#" class='delete'>删除</a>
            </td>
        </tr>
    `);
    }

3.5.4 新增图书功能

我们首先进行新增图书功能的编写,首先先获取到对应所需要的元素,然后实现点击新增图书,该表单显示的操作。

var addbook = document.querySelector('.addbook');
var btn = document.querySelector('#add');
var close1 = document.querySelector('#close');
btn.addEventListener('click', function () {
    addbook.style.display = 'block';
})

close1.addEventListener('click', function (e) {
    e.preventDefault();
    addbook.style.display = 'none';
})

该功能就编辑完成,此时点击新增图书,该表单就会显示出来。

接下来开始进行实现新增图书功能的操作,可以将新增的图书,不仅能够添加到浏览器的页面还能够添加到books.txt中去。

首先添加事件监听,当表单被提交时,会触发该事件。

在这个监听函数中获取表单数据,将表单中输入的数据提取出来,并存储在newbook对象中。

这个newbook对象,就是用来后面把新增的图书储存请求后端放到txt中的对象。

发送AJAX请求,使用jQuery的$.ajax()方法向后端发送HTTP请求。请求信息包括:

url: 发送请求的目标URL。

method: 请求的方法,这里使用POST。

contentType: 设置请求头为application/json,表示请求体内容为JSON格式。

data: 将newbook对象转换为JSON字符串,作为请求体发送。

并添加一个处理成功响应,若能成功响应,在回调中,将新书对象newbook添加到books数组中,调用updateTable()函数更新表格显示,并隐藏新增图书的表单。

这里的updateTable()函数将在后面进行编写,这个函数就是用来更新表格每当我们实现一个功能时,调用它来进行刷新。

处理错误响应,添加这个的目的就是我们在编写中难免会出现错误所以我们可以在当我们发生错误时,可以打印一下错误信息,并为之改错。使用error: 定义当请求失败时的回调函数。使用console.error()输出错误信息,便于调试。

Xhr:这是当 AJAX 请求发生错误时,错误回调函数的第一个参数。

新增图书代码:

document.getElementById('addform').addEventListener('submit', function (e) {
    e.preventDefault(); // 防止默认提交行为

    var newbook = {
        bookname: document.getElementById('bookname').value,
        author: document.getElementById('author').value,
        publisher: document.getElementById('publisher').value,
        publishdate: document.getElementById('publishdate').value,
        page: document.getElementById('page').value,
        price: document.getElementById('price').value,
        content: document.getElementById('content').value
    };

    // 使用 POST 方法,确保将数据作为请求体发送
    $.ajax({
        url: 'http://localhost:5501/addBook', // 后端处理的 URL
        method: 'POST',  // 使用 POST 方法
        contentType: 'application/json', // 设置请求头为 JSON
        data: JSON.stringify(newbook), // 将对象转换为 JSON 字符串
        success: function () {
            books.push(newbook); // 将新书加入数组
            updateTable(); // 更新表格
            addbook.style.display = 'none'; // 隐藏新增表单
        },
        error: function (xhr) {
            console.error('添加图书失败:', xhr.responseText); // 输出错误信息
        }
    });
});

 

3.5.6 删除书籍功能

这部分主要想实现删除图书的功能,首先进行的是一个委托事件绑定。绑定一个点击事件到表格的 .delete 类元素上。当用户点击某个删除链接时,触发这个事件处理函数。点击删除链接时会触发一个弹窗,并提示用户是否删除图书,如果用户选择“确定”,则继续执行后续代码,否则不采取任何行动。

接线来进行若点击删除,下面要执行的代码,首先要知道是哪行在请求删除,所以使用 $(this).closest('tr') 获取当前链接所在的行 (<tr>)。这样可以找到与点击的删除链接对应的数据行。

知道是哪行了以后,由于获取到的书籍是在刚刚新建的数组中,所以要获取行的索引并加上当前页的书籍数量,以计算出在 books 数组中的实际索引位置。这是确保正确定位要删除的书籍。

最后开始与后端相交互,发送删除请求,使用 DELETE 方法向指定的 URL 发送删除请求。注意端口名,再添加一个删除图书回调,若请求成功,则从数组中删除对应的书籍。再删除表格对应的行,最后更新分页信息。若请求失败,则要打印一下错误信息以方便改错。

$("table").on('click', ".delete", function () {
    if (confirm("是否确定删除图书")) {
        var tr = $(this).closest('tr'); // 获取当前行
        var bookIndex = tr.index() + (currentPage - 1) * booksPerPage; // 计算索引
        $.ajax({
            url: 'http://localhost:5501/books/' + bookIndex,  // 确保URL正确
            method: 'DELETE', // 使用 DELETE 方法
            success: function (response) {
                // 删除成功
                books.splice(bookIndex, 1); // 从数组中移除对应的书籍
                tr.remove(); // 删除表格中的行
                updatePagination(Math.ceil(books.length / booksPerPage)); // 更新分页信息
            },
            error: function (xhr, status, error) {
                console.error('删除图书失败:', xhr.responseText); // 输出错误信息
            }
        });
    }
});

注意:更新分页信息是为后期翻页功能中输出信息当前共几本书的函数。 

3.5.7 编辑图书功能

第一步与前两个功能一样,都可以使用事件委托来进行编辑操作。同样的方法先获取当前所在行,在通过计算分页的页数以及计算出书籍在 books 数组中的实际索引,从而获取对应的书籍数据。

接下来在点击编辑后出现的表单中,进行填充表单。

填充表单之后,管理员即开始对其书籍信息进行编辑,等待编辑完事,并点击提交时就会进行下一步编辑表单提交时处理更新。还是使用表单提交事件。

解除对表单提交事件的所有先前绑定,并定义新的提交处理逻辑。

注意:然后需要获取更新后的书籍信息,就是更改完之后的表单中每项对应的值构建一个 updatedBook 对象,该对象还会用于请求后端时,写入的内容。获取之后开始向后端发起AJAX请求,使用 PUT 方法向服务器发送更新的书籍信息。同样的请求头设置为 application/json,发送的请求体为 updatedBook 对象的 JSON 字符串格式。

请求更新编辑成功后,将更新后的书籍信息存回 books 数组中,并调用 updateTable() 函数刷新表格内容。最后,隐藏编辑表单。

若请求失败,输出错误信息到控制台,便于后续的修改。

    $('tbody').on('click', '.edit', function () {
        var tr = $(this).closest('tr'); // 获取当前行
        var bookIndex = tr.index() + (currentPage - 1) * booksPerPage; // 更新索引以便正确指向
        var book = books[bookIndex]; // 获取对应的书籍数据
        editbook.style.display = 'block'; // 显示编辑表单
        // 填充编辑表单
        document.getElementById('editform').reset(); // 清空表单
        document.querySelector('#editform input[name="bookname"]').value = book.bookname;
        document.querySelector('#editform input[name="author"]').value = book.author;
        document.querySelector('#editform input[name="publisher"]').value = book.publisher;
        document.querySelector('#editform input[name="publishdate"]').value = book.publishdate;
        document.querySelector('#editform input[name="page"]').value = book.page;
        document.querySelector('#editform input[name="price"]').value = book.price;
        document.querySelector('#editform textarea[name="content"]').value = book.content;

        

        // 在编辑表单提交时处理更新
        $('#editform').off('submit').on('submit', function (event) {
            event.preventDefault(); // 防止默认提交行为

            var updatedBook = {
                bookname: document.querySelector('#editform input[name="bookname"]').value,
                author: document.querySelector('#editform input[name="author"]').value,
                publisher: document.querySelector('#editform input[name="publisher"]').value,
                publishdate: document.querySelector('#editform input[name="publishdate"]').value,
                page: document.querySelector('#editform input[name="page"]').value,
                price: document.querySelector('#editform input[name="price"]').value,
                content: document.querySelector('#editform textarea[name="content"]').value
            };

            // 向服务器发送PUT请求更新书籍信息
            $.ajax({
                url: 'http://localhost:5501/books/' + bookIndex, // 使用正确的URL及ID
                method: 'PUT',  // 将方法改为 PUT
                contentType: 'application/json', // 设置请求头为 JSON
                data: JSON.stringify(updatedBook), // 将对象转换为 JSON 字符串
                success: function (response) {
                    // 更新数组中的数据
                    books[bookIndex] = updatedBook; // 更新对应索引的书籍信息
                    updateTable(); // 更新表格
                    editbook.style.display = 'none'; // 隐藏编辑表单
                },
                error: function (xhr) {
                    console.error('编辑图书失败:', xhr.responseText); // 输出错误信息
                }
            });
        });
    });
    // 更新分页信息
    updatePagination(totalPages);
}

3.5.8 翻页功能及更新分页信息(updatePagination

首先写一下更新的那些信息的函数,该函数接受参数 totalPages,更新页面上显示的总书籍数量和当前页码信息,确保管理员清楚现在的书籍数量。

  1. 翻到第一页:

当点击“第一页”按钮时,将 currentPage 设置为 1,并调用 updateTable() 更新表格内容,显示第一页的书籍。即会跳到第一页。

$('.nav #first-page').click(function () {
    currentPage = 1;
    updateTable();
});
  1. 翻到上一页:

点击“上一页”按钮时,如果当前页大于 1,则将 currentPage 减 1,并更新表格内容,显示上一页的书籍。

$('.nav #prev-page').click(function () {
    if (currentPage > 1) {
        currentPage--;
        updateTable();
    }
});
  1. 翻到下一页:

当点击“下一页”按钮时,首先计算总页数 totalPages。如果当前页小于总页数,则将 currentPage 加 1,并更新表格,显示下一页的书籍。

$('.nav #next-page').click(function () {
    const totalPages = Math.ceil(books.length / booksPerPage);
    if (currentPage < totalPages) {
        currentPage++;
        updateTable();
    }
});

  1. 翻到最后一页:

点击“最后一页”按钮时,直接将 currentPage 设置为最后一页的页码,然后更新表格以显示最后一页的书籍。

$('.nav #last-page').click(function () {
    currentPage = Math.ceil(books.length / booksPerPage);
    updateTable();
});
  1. 跳转到指定页:

当用户输入一个页码并点击“跳转”按钮时,首先通过 parseInt() 转换输入的值为整数。如果该页码大于 0 且小于等于总页数,则更新 currentPage,并调用 updateTable() 更新表格以显示相应的页。

$('.nav #jump-to-page').click(function () {
    const pageInput = parseInt($('.nav input[type="text"]').val());
    if (pageInput > 0 && pageInput <= Math.ceil(books.length / booksPerPage)) {
        currentPage = pageInput;
        updateTable();
    }
});

至此,图书管理的相关功能就写完了。

JS全部代码:

var addbook = document.querySelector('.addbook');
var container = document.querySelector('.container');
var close1 = document.querySelector('#close');
var btn = document.querySelector('#add');
var editbook = document.querySelector('.editbook');

btn.addEventListener('click', function () {
    addbook.style.display = 'block';
})

close1.addEventListener('click', function (e) {
    e.preventDefault();
    addbook.style.display = 'none';
})

//分页功能
// 书籍数据数组


// 新增图书
document.getElementById('addform').addEventListener('submit', function (e) {
    e.preventDefault(); // 防止默认提交行为

    var newbook = {
        bookname: document.getElementById('bookname').value,
        author: document.getElementById('author').value,
        publisher: document.getElementById('publisher').value,
        publishdate: document.getElementById('publishdate').value,
        page: document.getElementById('page').value,
        price: document.getElementById('price').value,
        content: document.getElementById('content').value
    };

    // 使用 POST 方法,确保将数据作为请求体发送
    $.ajax({
        url: 'http://localhost:5501/addBook', // 后端处理的 URL
        method: 'POST',  // 使用 POST 方法
        contentType: 'application/json', // 设置请求头为 JSON
        data: JSON.stringify(newbook), // 将对象转换为 JSON 字符串
        success: function () {
            books.push(newbook); // 将新书加入数组
            updateTable(); // 更新表格
            addbook.style.display = 'none'; // 隐藏新增表单
        },
        error: function (xhr) {
            console.error('添加图书失败:', xhr.responseText); // 输出错误信息
        }
    });
});
let books = [];
let currentPage = 1;
const booksPerPage = 5;
// 获取books.txt文件内容
$.get('/books.txt', function (data) {
    var usres = JSON.parse(data);
    books = usres; // 将文件内容存入数组
    updateTable(); // 更新表格
});

// 更新表格函数
function updateTable() {
    $('tbody').empty();
    const totalPages = Math.ceil(books.length / booksPerPage);
    const start = (currentPage - 1) * booksPerPage;
    const end = Math.min(start + booksPerPage, books.length);

    for (let i = start; i < end; i++) {
        const book = books[i];
        $('tbody').append(`
        <tr>
            <td>${book.bookname}</td>
            <td>${book.author}</td>
            <td>${book.publisher}</td>
            <td>${book.publishdate}</td>
            <td>${book.page}</td>
            <td>${book.price}</td>
            <td>${book.content}</td>
            <td>
                <a href="#" class='edit'>编辑</a>
                <a href="#" class='delete'>删除</a>
            </td>
        </tr>
    `);
    }


// //编辑操作
    // 使用事件委托处理动态生成的元素
    $('tbody').on('click', '.edit', function () {
        var tr = $(this).closest('tr'); // 获取当前行
        var bookIndex = tr.index() + (currentPage - 1) * booksPerPage; // 更新索引以便正确指向
        var book = books[bookIndex]; // 获取对应的书籍数据
        editbook.style.display = 'block'; // 显示编辑表单
        // 填充编辑表单
        document.getElementById('editform').reset(); // 清空表单
        document.querySelector('#editform input[name="bookname"]').value = book.bookname;
        document.querySelector('#editform input[name="author"]').value = book.author;
        document.querySelector('#editform input[name="publisher"]').value = book.publisher;
        document.querySelector('#editform input[name="publishdate"]').value = book.publishdate;
        document.querySelector('#editform input[name="page"]').value = book.page;
        document.querySelector('#editform input[name="price"]').value = book.price;
        document.querySelector('#editform textarea[name="content"]').value = book.content;

        

        // 在编辑表单提交时处理更新
        $('#editform').off('submit').on('submit', function (event) {
            event.preventDefault(); // 防止默认提交行为

            var updatedBook = {
                bookname: document.querySelector('#editform input[name="bookname"]').value,
                author: document.querySelector('#editform input[name="author"]').value,
                publisher: document.querySelector('#editform input[name="publisher"]').value,
                publishdate: document.querySelector('#editform input[name="publishdate"]').value,
                page: document.querySelector('#editform input[name="page"]').value,
                price: document.querySelector('#editform input[name="price"]').value,
                content: document.querySelector('#editform textarea[name="content"]').value
            };

            // 向服务器发送PUT请求更新书籍信息
            $.ajax({
                url: 'http://localhost:5501/books/' + bookIndex, // 使用正确的URL及ID
                method: 'PUT',  // 将方法改为 PUT
                contentType: 'application/json', // 设置请求头为 JSON
                data: JSON.stringify(updatedBook), // 将对象转换为 JSON 字符串
                success: function (response) {
                    // 更新数组中的数据
                    books[bookIndex] = updatedBook; // 更新对应索引的书籍信息
                    updateTable(); // 更新表格
                    editbook.style.display = 'none'; // 隐藏编辑表单
                },
                error: function (xhr) {
                    console.error('编辑图书失败:', xhr.responseText); // 输出错误信息
                }
            });
        });
    });

    // 更新分页信息
    updatePagination(totalPages);
}

// 删除书籍
$("table").on('click', ".delete", function () {
    if (confirm("是否确定删除图书")) {
        var tr = $(this).closest('tr'); // 获取当前行
        var bookIndex = tr.index() + (currentPage - 1) * booksPerPage; // 计算索引
        $.ajax({
            url: 'http://localhost:5501/books/' + bookIndex,  // 确保URL正确
            method: 'DELETE', // 使用 DELETE 方法
            success: function (response) {
                // 删除成功
                books.splice(bookIndex, 1); // 从数组中移除对应的书籍
                tr.remove(); // 删除表格中的行
                updatePagination(Math.ceil(books.length / booksPerPage)); // 更新分页信息
            },
            error: function (xhr, status, error) {
                console.error('删除图书失败:', xhr.responseText); // 输出错误信息
            }
        });
    }
});
// 更新分页信息
function updatePagination(totalPages) {
    $('.nav .total-records').text(`共${books.length}本书`);
    $('.nav .current-page').text(`当前第${currentPage}页/共${totalPages}页`);
}

// 翻页功能
$('.nav #first-page').click(function () {
    currentPage = 1;
    updateTable();
});

$('.nav #prev-page').click(function () {
    if (currentPage > 1) {
        currentPage--;
        updateTable();
    }
});

$('.nav #next-page').click(function () {
    const totalPages = Math.ceil(books.length / booksPerPage);
    if (currentPage < totalPages) {
        currentPage++;
        updateTable();
    }
});

$('.nav #last-page').click(function () {
    currentPage = Math.ceil(books.length / booksPerPage);
    updateTable();
});

$('.nav #jump-to-page').click(function () {
    const pageInput = parseInt($('.nav input[type="text"]').val());
    if (pageInput > 0 && pageInput <= Math.ceil(books.length / booksPerPage)) {
        currentPage = pageInput;
        updateTable();
    }
});

目前就差后端代码部分的编写了,加油坚持住下一章博客进行最后阶段的完成以及整合!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2262607.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot450房屋租赁管理系统(论文+源码)_kaic

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统房屋租赁管理系统信息管理难度大&#xff0c;容错率低&am…

vue框架的搭建

1什么是Node.js&#xff1b; Node.js 是一个免费、开源、跨平台的 JavaScript 运行时环境, 它让开发人员能够创建服务器 Web 应用、命令行工具和脚本 Node.js下载&#xff1a; 下载Node 16.20.2 安装Node.js 安装Node.js 测试安装 运行命令行 win键R 查看node版本 输入&am…

TCP基础了解

什么是 TCP &#xff1f; TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。 面向连接&#xff1a;一定是「一对一」才能连接&#xff0c;不能像 UDP 协议可以一个主机同时向多个主机发送消息&#xff0c;也就是一对多是无法做到的&#xff1b; 可靠的&#xff1a;无论…

电商数据采集电商,行业数据分析,平台数据获取|稳定的API接口数据

电商数据采集可以通过多种方式完成&#xff0c;其中包括人工采集、使用电商平台提供的API接口、以及利用爬虫技术等自动化工具。以下是一些常用的电商数据采集方法&#xff1a; 人工采集&#xff1a;人工采集主要是通过基本的“复制粘贴”的方式在电商平台上进行数据的收集&am…

C语言-稀疏数组转置

1.题目要求 2.代码实现 #include <stdio.h> #define MAX_TERM 80// 定义稀疏矩阵结构体 typedef struct juzhen {int row;int col;int value; } Juzhen;// 显示稀疏矩阵 void show(Juzhen a[], int count_a) {printf(" i row col val\n");for (int i 1; i &…

在 Spring Boot 3 中实现基于角色的访问控制

基于角色的访问控制 (RBAC) 是一种有价值的访问控制模型,可增强安全性、简化访问管理并提高效率。它在管理资源访问对安全和运营至关重要的复杂环境中尤其有益。 我们将做什么 我们有一个包含公共路由和受限路由的 Web API。受限路由需要数据库中用户的有效 JWT。 现在用户…

计算机毕业设计python+spark+hive动漫推荐系统 漫画推荐系统 漫画分析可视化大屏 漫画爬虫 漫画推荐系统 漫画爬虫 知识图谱 大数据毕设

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

SAP抓取外部https报错SSL handshake处理方法

一、问题描述 SAP执行报表抓取https第三方数据,数据获取失败。 报错消息: SSL handshake with XXX.COM:449 failed: SSSLERR_SSL_READ (-58)#SAPCRYPTO:SSL_read() failed##SapSSLSessionStartNB()==SSSLERR_SSL_READ# SSL:SSL_read() failed (536875120/0x20001070)# …

OpenCV基本图像处理操作(三)——图像轮廓

轮廓 cv2.findContours(img,mode,method) mode:轮廓检索模式 RETR_EXTERNAL &#xff1a;只检索最外面的轮廓&#xff1b;RETR_LIST&#xff1a;检索所有的轮廓&#xff0c;并将其保存到一条链表当中&#xff1b;RETR_CCOMP&#xff1a;检索所有的轮廓&#xff0c;并将他们组…

告别机器人味:如何让ChatGPT写出有灵魂的内容

目录 ChatGPT的一些AI味道小问题 1.提供编辑指南 2.提供样本 3.思维链大纲 4.融入自己的想法 5.去除重复增加多样性 6.删除废话 ChatGPT的一些AI味道小问题 大多数宝子们再使用ChatGPT进行写作时&#xff0c;发现我们的老朋友ChatGPT在各类写作上还有点“机器人味”太重…

对于给定PI参数的锁相环带宽简单计算方法

锁相环的控制框图一般为&#xff1a; 对于锁相环的闭环传递函数&#xff1a; H ( s ) K P L L p s K P L L i s 2 K P L L p s K P L L i H(s)\frac{K_{PLLp}sK_{PLLi}}{s^2K_{PLLp}sK_{PLLi}} H(s)s2KPLLp​sKPLLi​KPLLp​sKPLLi​​ 我们可以通过分析系统的特征方程&a…

day14-16系统服务管理和ntp和防火墙

一、自有服务概述 服务是一些特定的进程&#xff0c;自有服务就是系统开机后就自动运行的一些进程&#xff0c;一旦客户发出请求&#xff0c;这些进程就自动为他们提供服务&#xff0c;windows系统中&#xff0c;把这些自动运行的进程&#xff0c;称为"服务" window…

【数据集】玻璃门窗缺陷检测数据集3085张5类YIOLO+VOC格式

数据集格式&#xff1a;VOC格式YOLO格式 压缩包内含&#xff1a;3个文件夹&#xff0c;分别存储图片、xml、txt文件 JPEGImages文件夹中jpg图片总计&#xff1a;3085 Annotations文件夹中xml文件总计&#xff1a;3085 labels文件夹中txt文件总计&#xff1a;3085 标签种类数&am…

SLM510A系列——24V,15到150mA单通道可调电流线性恒流LED驱动芯片

SLM510A 系列产品是单通道、高精度、可调电流线性恒流源的 LED 驱动芯片&#xff0c;在各种 LED 照明产品中非常简单易用。其在宽电压输入范围内&#xff0c;能保证极高的输出电流精度&#xff0c;从而在大面积的光源照明中&#xff0c;都能让 LED 照明亮度保持均匀一致。 由于…

前后端联调环境配置

1、常规情况&#xff1a;登录页和后台管理系统是同一个IP地址 // vite.config.js import { defineConfig } from vite; import vue from vitejs/plugin-vue;// https://vitejs.dev/config/ export default defineConfig({plugins: [vue()],server: {proxy: {// 将本地的 /api …

ansible的流程控制

Ansible 剧本的流程控制通过任务的顺序执行、条件语句&#xff08;when&#xff09;、循环&#xff08;with_items 等&#xff09;、错误处理&#xff08;ignore_errors 和 block&#xff09;、以及任务标签和角色来实现。可以根据条件动态控制任务执行&#xff0c;使用循环处理…

初学stm32 --- 系统时钟配置

众所周知&#xff0c;时钟系统是 CPU 的脉搏&#xff0c;就像人的心跳一样。所以时钟系统的重要性就不言而喻了。 STM32 的时钟系统比较复杂&#xff0c;不像简单的 51 单片机一个系统时钟就可以解决一切。于是有人要问&#xff0c;采用一个系统时钟不是很简单吗&#xff1f;为…

王佩丰24节Excel学习笔记——第十一讲:Vlookup函数

【以 Excel2010 系列学习&#xff0c;用 Office LTSC 专业增强版 2021 实践】 【本章小技巧】 掌握vlookup使用方法&#xff0c;选区的第一列一定是查询参数条件一。使用通配符查询。vlookup 限 255 位长度。掌握日常使用场景。使用vlookup模糊匹配查询个税 一、使用Vlookup函…

3D和AR技术在电商行业的应用有哪些?

3D展示和AR技术在电商行业的应用为消费者带来了更为直观、沉浸式的购物体验&#xff0c;显著提升了商品展示效果和销售转化率。以下是3D和AR技术在电商行业的具体应用&#xff1a; 1、商品3D展示&#xff1a; 通过3D技术&#xff0c;商品可以在电商平台上以三维形式呈现&…

springboot中Controller内文件上传到本地以及阿里云

上传文件的基本操作 <form action"/upload" method"post" enctype"multipart/form-data"> <h1>登录</h1> 姓名&#xff1a;<input type"text" name"username" required><br> 年龄&#xf…