——动作:管理员登陆成功先进入主页面,点击书籍管理进行入书籍管理页面,如图4个分块,主要实现前三个。
有了这样的总体设计,首先所有页面的底部都公用,所以让其继承于主页面,那么势必要以共有部分作为父布局组件,其余通过路由跳转、又或者直接组件嵌套;公用底部,因此有了一个AdminLayOut,另外在里面设置背景颜色等基础;底部以上的头和体,则继续分,展示首页、三个底部按钮跳转的页面,他们公用左上角的icon,单独提出来,但是他们的头不一样,因此从这里形成了两组AdminHome和ManageBookLayout,AdminHome用于管理员第一次登陆的展示;ManageBookLayout用于数据管理页总组件,关于书籍管理,主要3个要实现的,他们的头、体都不一样,这里书籍管理页面以及三个功能页面也可以和AdminHome同级,这里之所以单独成ManageBookLayout,方便路由层级管理和理解,不然放一块太乱了。路由层级、文件结构如下图(右2副图)。
——动作:管理员点击增加书籍,进入增加书籍页面,输入书籍的6个信息,点击提交
——实现思路:管理员点击提交后,数据会通过发送请求,服务器通过监听端口,以及请求中的路由匹配机制,解析前端提交给服务器的数据,保存到数据库中,并返回数据保存的结果。
——前端代码逻辑:点击按钮后,页面拿到一份管理员输入的数据,通过调用二次封装的ajax,发送POST请求,主要代码如下:
constonFinish=async(values)=>{console.log('Receivedvaluesofform:',values,fileList);try{constresponse=awaitreqAddBook({author:values.author,bookName:values.bookName,bookInfo:values.bookInfo,publisher:values.publisher,bookNum:values.bookNum,bookImg:fileList[0].thumbUrl,});console.log("请求成功",response);if(response.data.status===1){navigate('/admin/manageBooks/addBook',{replace:false});}elseif(response.data.status===0){//如果当前用户已经存在就提示一下alert(response.data.msg)}}catch(error){console.log("请求失败",error);}}reqAddBook=data=>ajax(base.baseurl+base.addBook,data,'POST');//添加图书的接口,发送POST请求//服务器注册一个路由_管理员增加书籍router.post("/admin/manageBooks/addbook",(req,res)=>{addBookServer(req.body,res);})——后台逻辑:服务器接收到数据后,调用addBookServer函数对数据进行进一步处理,存如数据库。但是需要注意,考虑到用户可能同一本书多次添加,本系统没有在前端去加进一步的防误触判定,询问用户是否确定保存,之在服务器端做了判定:如果是同一本书,数量改为相加后的结果。
constBookModel=require("../src/db/book");constaddBookServer=(data,res)=>{BookModel.find({bookName:data.bookName,author:data.author,publisher:data.publisher},(err,docs)=>{if(docs.length>0){//修改数据库的bookNum属性+data.bookNum就行letbookNum=parseInt(docs[0].bookNum)+parseInt(data.bookNum);console.log(bookNum)BookModel.updateOne({bookName:data.bookName,author:data.author,publisher:data.publisher},{$set:{bookNum:bookNum}},(err)=>{if(!err)console.log('修改成功')console.log(err);})res.send({msg:"数据保存成功",status:1})}else{letmodel=newBookModel(data)model.save((err)=>{if(!err){console.log("数据保存成功");res.send({msg:"数据保存成功",status:1})}else{console.log("数据保存失败")res.send({msg:`该书已存在${docs.length}本`,status:0})}})}})}module.exports=addBookServer;基本的设计过程,3个功能点的设计都类似,代码我不一一去放了,只说一下思路和设计页面,方便理解。
(3)删除书籍
——动作:管理员点击删除书籍,进入删除书籍页面,输入书籍作者和书名,点击删除按钮,每次删除都把数据库的最新的5条消息返回展示在前端
——实现思路:管理员点击提交后,数据会通过发送请求,服务器通过监听端口,以及请求中的路由匹配机制,解析前端提交给服务器的数据,进行数据库数据的更新,并返回数据删除后的结果和删除日志记录。
——后端代码逻辑:服务器拿到数据后,先进行删除,如果删除结果中,删除数量>0,说明成功执行了删除,非无效删除(本没有这个书时进行的删除),保存删除记录,成功后返回最新的5条删除记录。
(4)更改书籍
——动作:管理员点击更改书籍,进入更改书籍页面,输入书籍作者和书名,点击检索按钮,如果能检索到,结果会作为输入框的默认值展示,否则会提示,没有这本书
——实现思路:管理员点击提交后,数据会通过发送请求,服务器通过监听端口,以及请求中的路由匹配机制,解析前端提交给服务器的数据。在这个功能模块里进行了两次请求发送,第一次检索,第二次数据更新,每次都返回数据更新结果。
——前端代码逻辑:点击按钮后,页面拿到一份管理员输入的数据,通过调用二次封装的ajax,发送POST请求;接收到后端返回的书籍信息,保存到本地state,作为输入框默认输入,管理员根据提示进一步填写数据并提交更新数据,在接受后台更新状态结果
——后端代码逻辑:服务器第一次拿到数据后,先进行检索,返回检索结果;第二次接收到服务器数据,进行数据更新。
(5)补充主页展示
主页:搜索框、推荐书籍展示、轮播图设置三个功能。
轮播图直接采用的antd4的样式;整体的设计逻辑是,点击设置---》出现图2,搜索框搜索书籍,数据展示在上方===》选择想要检索的书籍===》在下方选择想要放在轮播图中的书籍===》点击提交,回到图1。