1、渲染教师的复选框列表
添加新增老师页面代码和getTeachers函数
1、index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>学生管理系统</title>
</head>
<body>
<div>
<h2>新增班级</h2>
<div>
<div>
<label>班级名称</label>
<input type="text" id="addClassName"/>
</div>
<div>
<label>选择教师</label>
<div id="selectTeacher">
<!--动态渲染教师列表-->
</div>
</div>
<button id="addClassBtn">确认新增</button>
</div>
<div><hr/></div>
</div>
<div>
<h2>新增教师</h2>
<div>
<div>
<label>教师名称</label>
<input type="text" id="addTeacherName"/>
</div>
<button id="addTeacherBtn">确认新增</button>
</div>
<div><hr/></div>
</div>
<h2>新增学生</h2>
<div>
<div><label>学生姓名:</label><input type="text" id="addStudentsName"/> </div>
<div><label>学生年龄:</label><input type="text" id="addStudentsAge"/> </div>
<div>
<label>学生性别:</label>
<input type="radio" name="addStudentsGender" value="男"><label>男</label>
<input type="radio" name="addStudentsGender" value="女"><label>女</label>
</div>
<div>
<label>所属班级</label>
<select id="selectClasses">
</select>
</div>
<div>
<button id="addStudent">确认新增</button>
</div>
</div>
<h2>修改学生</h2>
<div>
<input type="hidden" id="updateStudentsId">
<div><label>学生姓名:</label><input type="text" id="updateStudentsName"/> </div>
<div><label>学生年龄:</label><input type="text" id="updateStudentsAge"/> </div>
<div>
<label>学生性别:</label>
<input type="radio" name="updateStudentsGender" value="男"><label>男</label>
<input type="radio" name="updateStudentsGender" value="女"><label>女</label>
</div>
<div>
<button id="updateStudent">确认修改</button>
</div>
</div>
<h2>查询学生</h2>
<div>
<select id="searchType">
<option value="name">姓名</option>
<option value="age">年龄</option>
<option value="gender">性别</option>
</select>
<input type="text" id="searchValue">
<button id="searchBtn">查询学生</button>
</div>
<h2>学生列表</h2>
<table>
<thead>
<tr>
<th>学生姓名</th>
<th>学生年龄</th>
<th>学生性别</th>
<th>所属班级</th>
<th>学生操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>20</td>
<td>男</td>
<td>
<button>修改 | 删除</button>
</td>
</tr>
</tbody>
</table>
<script src="./javascripts/jquery.min.js"></script>
<script>
//给一个全局变量来做查询
let data={ }
//页面刷新就开始做这两个方法
getStudents()//获取全部学生
getClassess()//获取全部班级
getTeachers()//获取全部老师
//获取全部学生
function getStudents(){
$.ajax({
url:'/students/getStudents',
data:data,
type:'GET',
success({message,status,data }){
//进入if表示进入学生数据成功
if(status){
const str=data.map(function (item,index) {
return `
<tr>
<td>${item.name}</td>
<td>${item.age}</td>
<td>${item.gender}</td>
<td>${item.classId.name}</td>
<td>
<button class="updateBtn" data-id="${item._id}">修改</button>
<button class="removeBtn" data-id="${item._id}">删除</button>
</td>
</tr>
`
}).join('')//join是拼接
$('tbody').html(str)
}
}
})
}
//获取班级
function getClassess(){
$.ajax({
url:'/classes/getClasses',
type:'GET',
data:{},
success(msg){
if (msg.status){
const str=msg.data.map(function(item,index){
return `<option value="${item._id}">${item.name}</option>`
}).join('')//遍历出来data的name后,和option一起拼接成一个大字符串
$('#selectClasses').html(str)
}
}
})
}
//获取全部教师
function getTeachers(){
$.ajax({
url:'/teachers/getTeachers',
type:'GET',
success(msg){
if (msg.status){
const str=msg.data.map(item=>{
return`
<input type="checkbox" value="${item._id}"/>
<label>${item.name}</label>
`
}).join('')
$('#selectTeacher').html(str)
}
}
})
}
//新增班级
$('#addClassBtn').click(function(){
$.ajax({
url:'/classes/addClasses',
type:'POST',
data:{
name:$('#addClassName').val()
},
success(msg){
if (msg.status){
getClassess()
}
}
})
})
//删除按钮使用事件委托
//on做委托,委托给父级的静态元素,第一个参数是事件,第二个参数是真正执行的那个标签(委托人),第三个参数是具体的工作
$('tbody').on('click','.removeBtn',function(){
//获取当前点击的这个按钮对应的id,data('id')是获取所有(特定)属性的函数,这里的id实际就是data-id,前面加data-是一种约定俗成
const _id=$(this).data('id')
console.log(_id)
$.ajax({
url:'/students/deleteStudents',
type:'post',
data: { _id },
success (msg) {
if (msg.status){
alert('删除成功')
//重新发一次ajax请求
getStudents()
}
}
})
})
//修改学生信息
//获取要修改的一个学生信息
$('tbody').on('click','.updateBtn',function(){
const _id=$(this).data('id')
//console.log(_id)
$.ajax({
url:'/students/getStudentsById',
data:{_id},
success(msg){
if (msg.status){
$('#updateStudentsId').val(msg.data._id)
$('#updateStudentsName').val(msg.data.name)//设置控件的value值
$('#updateStudentsAge').val(msg.data.age)//设置控件的value值
$(`[name=updateStudentsGender][value=${msg.data.gender}]`).prop('checked',true)
}
}
})
})
//确认修改学生信息
$('#updateStudent').click(function(){
const _id=$('#updateStudentsId').val()
const name=$('#updateStudentsName').val()
const age=$('#updateStudentsAge').val()
const gender=$(`[name=updateStudentsGender]:checked`).val()
//console.log(name,age,gender)
$.ajax({
url:'/students/updateStudents',
type:'POST',
data:{
name,age,gender,_id
},
success(msg){
if(msg.status){
getStudents()
}
}
})
})
//查询
$('#searchBtn').click(function(){
//获取下拉列表中选中的option的value值,可以直接获取selected的值
const searchType=$('#searchType').val()
//console.log(searchType)
//获取搜索的值
const searchValue=$('#searchValue').val()
data={
searchType,
searchValue
}
//console.log(data)
getStudents()
})
//新增学生
$('#addStudent').click(function(){
const name=$('#addStudentsName').val()
const age=$('#addStudentsAge').val()
const gender=$('[name=addStudentsGender]:checked').val()
const classId=$('#selectClasses').val()
//console.log(name,age,gender)
$.ajax({
url:'/students/addStudents',
type:'POST',
data:{
name,
age,
gender,
classId
},
success(msg){
if (msg.status){
getStudents()
}
}
})
})
</script>
</body>
</html>
2、添加以及路由app.js
const teachersRouter=require('./routes/teachers')
app.use('/teachers', teachersRouter)
3、添加二级路由router/teachers.js
var express = require('express');
var router = express.Router();
//引入第二层的getStudents方法
const {getTeachers}=require('../service/teachersService')
//获取所有数据,及查询
router.get('/getTeachers', async function(req, res, next) {
const data=await getTeachers()
res.send(data)
});
module.exports = router;
4、添加服务成teacherService.js
const {getTeachers}=require('../dao/teachersDao')
//添加班级
module.exports.getTeachers=async function(){
const data=await getTeachers()
return {
message:'班级新增成功',
status:1,
data
}
}
5、添加服模型teacherModel.js
//数据集合的相关配置
//1、定义数据集合的结构:定义集合中数据有哪些属性,属性的值是什么类型(数据库结构)
//解构出mongoose的Schema方法来,这个方法用来操作集合的
const { Schema,model }=require('mongoose')
//通过构造函数创建集合的结构
const teachersSchema=new Schema({
name:String,
phone: {
type:String,
default:'18514125625'
},
},{versionKey:false})
//2、定义数据集合的模型:将schema和数据库中的集合关联起来
//model需要三个参数:模型名称,schema名称,数据库中的集合名称
const teachersModel=model('teachersModel',teachersSchema,'teachers')
//向第三层dao层暴露model数据
module.exports.teachersModel=teachersModel
6、添加持久层teacherDao.js
//引入第三层dao层的model模型,用以操作数据库
const { teachersModel }=require('./models/teachersModel')
//暴露一个获取所有学生方法
module.exports.getTeachers=async function () {
//find 是异步操作,在model里查找user记录(文档)。返回一个数组
//populate是做关联查询
const data=await teachersModel.find()
return data
}
2、新增班级是关联教师
新增班级部分添加遍历教师的部分
1、index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>学生管理系统</title>
</head>
<body>
<div>
<h2>新增班级</h2>
<div>
<div>
<label>班级名称</label>
<input type="text" id="addClassName"/>
</div>
<div>
<label>选择教师</label>
<div id="selectTeacher">
<!--动态渲染教师列表-->
</div>
</div>
<button id="addClassBtn">确认新增</button>
</div>
<div><hr/></div>
</div>
<div>
<h2>新增教师</h2>
<div>
<div>
<label>教师名称</label>
<input type="text" id="addTeacherName"/>
</div>
<button id="addTeacherBtn">确认新增</button>
</div>
<div><hr/></div>
</div>
<h2>新增学生</h2>
<div>
<div><label>学生姓名:</label><input type="text" id="addStudentsName"/> </div>
<div><label>学生年龄:</label><input type="text" id="addStudentsAge"/> </div>
<div>
<label>学生性别:</label>
<input type="radio" name="addStudentsGender" value="男"><label>男</label>
<input type="radio" name="addStudentsGender" value="女"><label>女</label>
</div>
<div>
<label>所属班级</label>
<select id="selectClasses">
</select>
</div>
<div>
<button id="addStudent">确认新增</button>
</div>
</div>
<h2>修改学生</h2>
<div>
<input type="hidden" id="updateStudentsId">
<div><label>学生姓名:</label><input type="text" id="updateStudentsName"/> </div>
<div><label>学生年龄:</label><input type="text" id="updateStudentsAge"/> </div>
<div>
<label>学生性别:</label>
<input type="radio" name="updateStudentsGender" value="男"><label>男</label>
<input type="radio" name="updateStudentsGender" value="女"><label>女</label>
</div>
<div>
<button id="updateStudent">确认修改</button>
</div>
</div>
<h2>查询学生</h2>
<div>
<select id="searchType">
<option value="name">姓名</option>
<option value="age">年龄</option>
<option value="gender">性别</option>
</select>
<input type="text" id="searchValue">
<button id="searchBtn">查询学生</button>
</div>
<h2>学生列表</h2>
<table>
<thead>
<tr>
<th>学生姓名</th>
<th>学生年龄</th>
<th>学生性别</th>
<th>所属班级</th>
<th>学生操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>20</td>
<td>男</td>
<td>
<button>修改 | 删除</button>
</td>
</tr>
</tbody>
</table>
<script src="./javascripts/jquery.min.js"></script>
<script>
//给一个全局变量来做查询
let data={ }
//页面刷新就开始做这两个方法
getStudents()//获取全部学生
getClassess()//获取全部班级
getTeachers()//获取全部老师
//获取全部学生
function getStudents(){
$.ajax({
url:'/students/getStudents',
data:data,
type:'GET',
success({message,status,data }){
//进入if表示进入学生数据成功
if(status){
const str=data.map(function (item,index) {
return `
<tr>
<td>${item.name}</td>
<td>${item.age}</td>
<td>${item.gender}</td>
<td>${item.classId.name}</td>
<td>
<button class="updateBtn" data-id="${item._id}">修改</button>
<button class="removeBtn" data-id="${item._id}">删除</button>
</td>
</tr>
`
}).join('')//join是拼接
$('tbody').html(str)
}
}
})
}
//获取班级
function getClassess(){
$.ajax({
url:'/classes/getClasses',
type:'GET',
data:{},
success(msg){
if (msg.status){
const str=msg.data.map(function(item,index){
return `<option value="${item._id}">${item.name}</option>`
}).join('')//遍历出来data的name后,和option一起拼接成一个大字符串
$('#selectClasses').html(str)
}
}
})
}
//获取全部教师
function getTeachers(){
$.ajax({
url:'/teachers/getTeachers',
type:'GET',
success(msg){
if (msg.status){
const str=msg.data.map(item=>{
return`
<input type="checkbox" value="${item._id}"/>
<label>${item.name}</label>
`
}).join('')
$('#selectTeacher').html(str)
}
}
})
}
//新增班级
$('#addClassBtn').click(function(){
//获取选中教师的id数组,使用扩展运算符转换为真数组
const teachersId=[...$('#selectTeacher>input[type=checkbox]:checked')].map(function(item,index){
//return item.value//原生js方法
return $(item).val()//jquery方法
})
//console.log(teachersId)
$.ajax({
url:'/classes/addClasses',
type:'POST',
data:{
name:$('#addClassName').val(),
teachersId
},
//当ajax的data传递数组的时候必须要添加选项解决数组格式问题
traditional:true,
success(msg){
if (msg.status){
getClassess()
}
}
})
})
//删除按钮使用事件委托
//on做委托,委托给父级的静态元素,第一个参数是事件,第二个参数是真正执行的那个标签(委托人),第三个参数是具体的工作
$('tbody').on('click','.removeBtn',function(){
//获取当前点击的这个按钮对应的id,data('id')是获取所有(特定)属性的函数,这里的id实际就是data-id,前面加data-是一种约定俗成
const _id=$(this).data('id')
console.log(_id)
$.ajax({
url:'/students/deleteStudents',
type:'post',
data: { _id },
success (msg) {
if (msg.status){
alert('删除成功')
//重新发一次ajax请求
getStudents()
}
}
})
})
//修改学生信息
//获取要修改的一个学生信息
$('tbody').on('click','.updateBtn',function(){
const _id=$(this).data('id')
//console.log(_id)
$.ajax({
url:'/students/getStudentsById',
data:{_id},
success(msg){
if (msg.status){
$('#updateStudentsId').val(msg.data._id)
$('#updateStudentsName').val(msg.data.name)//设置控件的value值
$('#updateStudentsAge').val(msg.data.age)//设置控件的value值
$(`[name=updateStudentsGender][value=${msg.data.gender}]`).prop('checked',true)
}
}
})
})
//确认修改学生信息
$('#updateStudent').click(function(){
const _id=$('#updateStudentsId').val()
const name=$('#updateStudentsName').val()
const age=$('#updateStudentsAge').val()
const gender=$(`[name=updateStudentsGender]:checked`).val()
//console.log(name,age,gender)
$.ajax({
url:'/students/updateStudents',
type:'POST',
data:{
name,age,gender,_id
},
success(msg){
if(msg.status){
getStudents()
}
}
})
})
//查询
$('#searchBtn').click(function(){
//获取下拉列表中选中的option的value值,可以直接获取selected的值
const searchType=$('#searchType').val()
//console.log(searchType)
//获取搜索的值
const searchValue=$('#searchValue').val()
data={
searchType,
searchValue
}
//console.log(data)
getStudents()
})
//新增学生
$('#addStudent').click(function(){
const name=$('#addStudentsName').val()
const age=$('#addStudentsAge').val()
const gender=$('[name=addStudentsGender]:checked').val()
const classId=$('#selectClasses').val()
//console.log(name,age,gender)
$.ajax({
url:'/students/addStudents',
type:'POST',
data:{
name,
age,
gender,
classId
},
success(msg){
if (msg.status){
getStudents()
}
}
})
})
</script>
</body>
</html>
2、修改classessModel.js
由于调整了班级对应教师的模型,一般对多个教师,所以要修改classessModel
//数据集合的相关配置
//1、定义数据集合的结构:定义集合中数据有哪些属性,属性的值是什么类型(数据库结构)
//解构出mongoose的Schema方法来,这个方法用来操作集合的
const { Schema,model }=require('mongoose')
//通过构造函数创建集合的结构
const classesSchema=new Schema({
name:String,
//teahersid实际是数组(一对多),所以要加中括号变成数组
teachersId: [{
type:Schema.Types.ObjectId,
ref:'teachersModel'
}]
},{versionKey:false})
//2、定义数据集合的模型:将schema和数据库中的集合关联起来
//model需要三个参数:模型名称,schema名称,数据库中的集合名称
const classesModel=model('classesModel',classesSchema,'classes')
//向第三层dao层暴露model数据
module.exports.classesModel=classesModel
3、populate嵌套关联查询
index页面中添加增加学生、班级、教师关联语句
1、index.html
2、在studentsDao.js中获取学生处理函数中,添加populate设置,注意对于teachersId使用关联语法
const data=await studentsModel.find().populate({
path:'classId',
populate:{
path:'teachersId'
}
})
完整studentsDao.js代码
//向第二层服务层暴露getStudents方法,
//在第三层dao层操作数据库
//引入第三层dao层的model模型,用以操作数据库
const { studentsModel }=require('./models/studentsModel')
//暴露一个获取所有学生方法
module.exports.getStudents=async function () {
//find 是异步操作,在model里查找user记录(文档)。返回一个数组
//populate是做关联查询
const data=await studentsModel.find().populate({
path:'classId',
populate:{
path:'teachersId'
}
})
//console.log('第三层的data',data)
//第三层直接返回数据给第二层,不需要做任何操作,dao层-->服务层-->表现层
return data
//做模糊查询
// return await studentsModel.find({
// //$options:'$i'因为不区分大小写
// [params.searchType]:{$regex:params.searchValue,$options:'$i'}
// })
}
//暴露一个获取部分学生方法
module.exports.searchStudents=async function (params) {
//做模糊查询
return await studentsModel.find({
//$options:'$i'因为不区分大小写
// [params.searchType]:{$regex:params.searchValue,$options:'$i'}
// }).populate('classId')
[params.searchType]:{$regex:params.searchValue,$options:'$i'}
}).populate( 'classId' )
}
//暴露一个新增方法
module.exports.addStudents=async function (student) {
const data=await studentsModel.create(student)
return data
}
//暴露一个删除方法
module.exports.deleteStudents=async function ({ _id }) {//这里把对象中的id解构出来了
//const data=await studentsModel.deleteOne(_id)//这里id实际是一个对象
const data=await studentsModel.findByIdAndDelete(_id)
return data
}
//暴露一个获取学生方法
module.exports.getStudentsById=async function ({ _id }) {//这里把对象中的id解构出来了
//const data=await studentsModel.deleteOne(_id)//这里id实际是一个对象
const data=await studentsModel.findById(_id)//返回的事一个对象
return data
}
//确认修改一个学生方法
module.exports.updateStudents=async function ({_id,name,age,gender }) {//这里把对象中的id解构出来了
//console.log(student)
//const data=await studentsModel.deleteOne(_id)//这里id实际是一个对象
//return await studentsModel.updateOne({_id:student._id},student)//返回的事一个对象
return await studentsModel.findByIdAndUpdate(_id, { name,age,gender})//返回的事一个对象
}
4、实现分页方式的选择及页面渲染
1、一次渲染,分页显示
2、分页渲染
在页面需要做响应的修改
步骤上
1、给页面ajax传递的参数添加一个pageSize属性和一个currentSize属性
//获取全部学生
function getStudents(){
$.ajax({
url:'/students/getStudents',
data: {
...data,//先前传递的data对象
pageSize:5,//每页显示条数
currentPage:1//当前页
},
type:'GET',
success({message,status,data }){
//console.log(data)
//进入if表示进入学生数据成功
if(status){
const str=data.map(function (item,index) {
return `
<tr>
<td>${item.name}</td>
<td>${item.age}</td>
<td>${item.gender}</td>
<td>${item.classId.name}</td>
<td>
${
item.classId.teachersId.map(item=>`<p>${item.name}</p>`).join('')
}
</td>
<td>
<button class="updateBtn" data-id="${item._id}">修改</button>
<button class="removeBtn" data-id="${item._id}">删除</button>
</td>
</tr>
`
}).join('')//join是拼接
$('tbody').html(str)
}
}
})
}
2、在service分别给getstudents函数添加一个参数params
studentsService.js
module.exports.getStudents= async function (params) {
//console.log('第二层学生数据',params)
//根据参数情况判断查询什么
//进入if表示searchValue有值,说明是获取部分学生
if (params.searchValue){
const data=await searchStudents(params)
return {
message:'学生数据获取成功',
status:1,
data
}
}else{
//进入else表示searchValue没有值,说明是获取所有学生
//调用第三层(dao层)的login,数据从第二次(服务层)传递到了第三层(dao)层
try{
const data=await getStudents(params)
return {
message:'学生数据获取成功',
status:1,
data
}
//console.log('第二层的data',data)
}catch (e) {
console.log(e)
return {
message:'学生数据获取失败',
status:0
}
}
}
}
3、调整dao层的查询代码使用limit()限制查询条数,使用skip()跳过一定条数
module.exports.getStudents=async function ({pageSize,currentPage }) {
//console.log('第三层的数据',pageSize,currentPage)
//find 是异步操作,在model里查找user记录(文档)。返回一个数组
//populate是做关联查询
const data=await studentsModel.find()
.populate({
path:'classId',
populate:{
path:'teachersId'
}
}).limit(pageSize-0)//设置请求的数据条数
.skip((currentPage-1)*pageSize)//跳过数据的条数
完整代码如下:
1、index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>学生管理系统</title>
</head>
<body>
<div>
<h2>新增班级</h2>
<div>
<div>
<label>班级名称</label>
<input type="text" id="addClassName"/>
</div>
<div>
<label>选择教师</label>
<div id="selectTeacher">
<!--动态渲染教师列表-->
</div>
</div>
<button id="addClassBtn">确认新增</button>
</div>
<div><hr/></div>
</div>
<div>
<h2>新增教师</h2>
<div>
<div>
<label>教师名称</label>
<input type="text" id="addTeacherName"/>
</div>
<button id="addTeacherBtn">确认新增</button>
</div>
<div><hr/></div>
</div>
<h2>新增学生</h2>
<div>
<div><label>学生姓名:</label><input type="text" id="addStudentsName"/> </div>
<div><label>学生年龄:</label><input type="text" id="addStudentsAge"/> </div>
<div>
<label>学生性别:</label>
<input type="radio" name="addStudentsGender" value="男"><label>男</label>
<input type="radio" name="addStudentsGender" value="女"><label>女</label>
</div>
<div>
<label>所属班级</label>
<select id="selectClasses">
</select>
</div>
<div>
<button id="addStudent">确认新增</button>
</div>
</div>
<h2>修改学生</h2>
<div>
<input type="hidden" id="updateStudentsId">
<div><label>学生姓名:</label><input type="text" id="updateStudentsName"/> </div>
<div><label>学生年龄:</label><input type="text" id="updateStudentsAge"/> </div>
<div>
<label>学生性别:</label>
<input type="radio" name="updateStudentsGender" value="男"><label>男</label>
<input type="radio" name="updateStudentsGender" value="女"><label>女</label>
</div>
<div>
<button id="updateStudent">确认修改</button>
</div>
</div>
<h2>查询学生</h2>
<div>
<select id="searchType">
<option value="name">姓名</option>
<option value="age">年龄</option>
<option value="gender">性别</option>
</select>
<input type="text" id="searchValue">
<button id="searchBtn">查询学生</button>
</div>
<h2>学生列表</h2>
<table>
<thead>
<tr>
<th>学生姓名</th>
<th>学生年龄</th>
<th>学生性别</th>
<th>所属班级</th>
<th>负责教师</th>
<th>学生操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>20</td>
<td>男</td>
<td>
<button>修改 | 删除</button>
</td>
</tr>
</tbody>
</table>
<div>
<label>每页条数</label>
<select id="pageSize">
<option value="2">2</option>
<option value="3">3</option>
<option value="5">5</option>
</select>
</div>
<div>
<button>首页</button>
<button>下一页</button>
<button>上一页</button>
<button>尾页</button>
</div>
<script src="./javascripts/jquery.min.js"></script>
<script>
//给一个全局变量来做查询
let data={ }
//页面刷新就开始做这两个方法
getStudents()//获取全部学生
getClasses()//获取全部班级
getTeachers()//获取全部老师
//获取全部学生
function getStudents(){
$.ajax({
url:'/students/getStudents',
data: {
...data,
pageSize:5,//每页显示条数
currentPage:1//当前页
},
type:'GET',
success({message,status,data }){
//console.log(data)
//进入if表示进入学生数据成功
if(status){
const str=data.map(function (item,index) {
return `
<tr>
<td>${item.name}</td>
<td>${item.age}</td>
<td>${item.gender}</td>
<td>${item.classId.name}</td>
<td>
${
item.classId.teachersId.map(item=>`<p>${item.name}</p>`).join('')
}
</td>
<td>
<button class="updateBtn" data-id="${item._id}">修改</button>
<button class="removeBtn" data-id="${item._id}">删除</button>
</td>
</tr>
`
}).join('')//join是拼接
$('tbody').html(str)
}
}
})
}
//获取班级
function getClasses(){
$.ajax({
url:'/classes/getClasses',
type:'GET',
data:{},
success(msg){
if (msg.status){
const str=msg.data.map(function(item,index){
return `<option value="${item._id}">${item.name}</option>`
}).join('')//遍历出来data的name后,和option一起拼接成一个大字符串
$('#selectClasses').html(str)
}
}
})
}
//获取全部教师
function getTeachers(){
$.ajax({
url:'/teachers/getTeachers',
type:'GET',
success(msg){
if (msg.status){
const str=msg.data.map(item=>{
return`
<input type="checkbox" value="${item._id}"/>
<label>${item.name}</label>
`
}).join('')
$('#selectTeacher').html(str)
}
}
})
}
//新增班级
$('#addClassBtn').click(function(){
//获取选中教师的id数组,使用扩展运算符转换为真数组
const teachersId=[...$('#selectTeacher>input[type=checkbox]:checked')].map(function(item,index){
//return item.value//原生js方法
return $(item).val()//jquery方法
})
//console.log(teachersId)
$.ajax({
url:'/classes/addClasses',
type:'POST',
data:{
name:$('#addClassName').val(),
teachersId
},
//当ajax的data传递数组的时候必须要添加选项解决数组格式问题
traditional:true,
success(msg){
if (msg.status){
getClasses()
}
}
})
})
//删除按钮使用事件委托
//on做委托,委托给父级的静态元素,第一个参数是事件,第二个参数是真正执行的那个标签(委托人),第三个参数是具体的工作
$('tbody').on('click','.removeBtn',function(){
//获取当前点击的这个按钮对应的id,data('id')是获取所有(特定)属性的函数,这里的id实际就是data-id,前面加data-是一种约定俗成
const _id=$(this).data('id')
console.log(_id)
$.ajax({
url:'/students/deleteStudents',
type:'post',
data: { _id },
success (msg) {
if (msg.status){
alert('删除成功')
//重新发一次ajax请求
getStudents()
}
}
})
})
//修改学生信息
//获取要修改的一个学生信息
$('tbody').on('click','.updateBtn',function(){
const _id=$(this).data('id')
//console.log(_id)
$.ajax({
url:'/students/getStudentsById',
data:{_id},
success(msg){
if (msg.status){
$('#updateStudentsId').val(msg.data._id)
$('#updateStudentsName').val(msg.data.name)//设置控件的value值
$('#updateStudentsAge').val(msg.data.age)//设置控件的value值
$(`[name=updateStudentsGender][value=${msg.data.gender}]`).prop('checked',true)
}
}
})
})
//确认修改学生信息
$('#updateStudent').click(function(){
const _id=$('#updateStudentsId').val()
const name=$('#updateStudentsName').val()
const age=$('#updateStudentsAge').val()
const gender=$(`[name=updateStudentsGender]:checked`).val()
//console.log(name,age,gender)
$.ajax({
url:'/students/updateStudents',
type:'POST',
data:{
name,age,gender,_id
},
success(msg){
if(msg.status){
getStudents()
}
}
})
})
//查询
$('#searchBtn').click(function(){
//获取下拉列表中选中的option的value值,可以直接获取selected的值
const searchType=$('#searchType').val()
//console.log(searchType)
//获取搜索的值
const searchValue=$('#searchValue').val()
data={
searchType,
searchValue
}
//console.log(data)
getStudents()
})
//新增学生
$('#addStudent').click(function(){
const name=$('#addStudentsName').val()
const age=$('#addStudentsAge').val()
const gender=$('[name=addStudentsGender]:checked').val()
const classId=$('#selectClasses').val()
//console.log(name,age,gender)
$.ajax({
url:'/students/addStudents',
type:'POST',
data:{
name,
age,
gender,
classId
},
success(msg){
if (msg.status){
getStudents()
}
}
})
})
</script>
</body>
</html>
2、studentsService.js
const {getStudents,addStudents,deleteStudents,searchStudents,getStudentsById,updateStudents}=require('../dao/studentsDao')
//在第二层服务层暴露一个属性login给第一层(表现层),并从第一层接收一个数据user到第二层
//获取所有或获取部分学生
module.exports.getStudents= async function (params) {
//console.log('第二层学生数据',params)
//根据参数情况判断查询什么
//进入if表示searchValue有值,说明是获取部分学生
if (params.searchValue){
const data=await searchStudents(params)
return {
message:'学生数据获取成功',
status:1,
data
}
}else{
//进入else表示searchValue没有值,说明是获取所有学生
//调用第三层(dao层)的login,数据从第二次(服务层)传递到了第三层(dao)层
try{
const data=await getStudents(params)
return {
message:'学生数据获取成功',
status:1,
data
}
//console.log('第二层的data',data)
}catch (e) {
console.log(e)
return {
message:'学生数据获取失败',
status:0
}
}
}
}
//新增学生
module.exports.addStudents= async function (student) {
//调用第三层(dao层)的login,数据从第二次(服务层)传递到了第三层(dao)层
const data= await addStudents(student)
//console.log('第二层得到的data:',data)
if (data._id){
return {
message:'新增学生成功',
status:1,
data
}
}else{
return {
message:'新增学生失败',
status:0
}
}
}
//删除学生
module.exports.deleteStudents= async function (_id) {
//调用第三层(dao层)的login,数据从第二次(服务层)传递到了第三层(dao)层
const data= await deleteStudents(_id)
//console.log('第二层的data',data)
if (data){//如果data有值
return {
message:'删除成功',
status:1,
data
}
}else{
return {
message:'删除失败',
status:0,
}
}
}
//获取一个学生
module.exports.getStudentsById= async function (_id) {
//调用第三层(dao层)的login,数据从第二次(服务层)传递到了第三层(dao)层
const data= await getStudentsById(_id)
return {
message:'学生数据获取成功',
status:1,
data
}
}
//确认修改一个学生
module.exports.updateStudents= async function (student) {
//调用第三层(dao层)的login,数据从第二次(服务层)传递到了第三层(dao)层
const data= await updateStudents(student)
//console.log(data)
if (data){
return {
message:'修改学生数据成功',
status:1,
data
}
}else{
return {
message:'修改学生数据成功',
status:0
}
}
}
3、studentsDao.js
//向第二层服务层暴露getStudents方法,
//在第三层dao层操作数据库
//引入第三层dao层的model模型,用以操作数据库
const { studentsModel }=require('./models/studentsModel')
//暴露一个获取所有学生方法
module.exports.getStudents=async function ({pageSize,currentPage }) {
//console.log('第三层的数据',pageSize,currentPage)
//find 是异步操作,在model里查找user记录(文档)。返回一个数组
//populate是做关联查询
const data=await studentsModel.find()
.populate({
path:'classId',
populate:{
path:'teachersId'
}
}).limit(pageSize-0)//设置请求的数据条数
.skip((currentPage-1)*pageSize)//跳过数据的条数
//console.log('第三层的data',data)
//第三层直接返回数据给第二层,不需要做任何操作,dao层-->服务层-->表现层
return data
//做模糊查询
// return await studentsModel.find({
// //$options:'$i'因为不区分大小写
// [params.searchType]:{$regex:params.searchValue,$options:'$i'}
// })
}
//暴露一个获取部分学生方法
module.exports.searchStudents=async function (params) {
//做模糊查询
return await studentsModel.find({
//$options:'$i'因为不区分大小写
// [params.searchType]:{$regex:params.searchValue,$options:'$i'}
// }).populate('classId')
[params.searchType]:{$regex:params.searchValue,$options:'$i'}
}).populate( 'classId' )
}
//暴露一个新增方法
module.exports.addStudents=async function (student) {
const data=await studentsModel.create(student)
return data
}
//暴露一个删除方法
module.exports.deleteStudents=async function ({ _id }) {//这里把对象中的id解构出来了
//const data=await studentsModel.deleteOne(_id)//这里id实际是一个对象
const data=await studentsModel.findByIdAndDelete(_id)
return data
}
//暴露一个获取学生方法
module.exports.getStudentsById=async function ({ _id }) {//这里把对象中的id解构出来了
//const data=await studentsModel.deleteOne(_id)//这里id实际是一个对象
const data=await studentsModel.findById(_id)//返回的事一个对象
return data
}
//确认修改一个学生方法
module.exports.updateStudents=async function ({_id,name,age,gender }) {//这里把对象中的id解构出来了
//console.log(student)
//const data=await studentsModel.deleteOne(_id)//这里id实际是一个对象
//return await studentsModel.updateOne({_id:student._id},student)//返回的事一个对象
return await studentsModel.findByIdAndUpdate(_id, { name,age,gender})//返回的事一个对象
}
5、上一页和下一页的处理
使用三个点扩展父还能保留原有的数据(具体原理是什么)
data={
...data,//保留原有的data数据
searchType,
searchValue
}
这里重点是需要获取页数
在dao里通过 const total=await studentsModel.countDocuments()
获取总的记录条数并计算出总的页数
//获取查询的总条数
const total=await studentsModel.countDocuments()
//计算总页数
const pages=Math.ceil(total/pageSize)
1、index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>学生管理系统</title>
</head>
<body>
<div>
<h2>新增班级</h2>
<div>
<div>
<label>班级名称</label>
<input type="text" id="addClassName"/>
</div>
<div>
<label>选择教师</label>
<div id="selectTeacher">
<!--动态渲染教师列表-->
</div>
</div>
<button id="addClassBtn">确认新增</button>
</div>
<div><hr/></div>
</div>
<div>
<h2>新增教师</h2>
<div>
<div>
<label>教师名称</label>
<input type="text" id="addTeacherName"/>
</div>
<button id="addTeacherBtn">确认新增</button>
</div>
<div><hr/></div>
</div>
<h2>新增学生</h2>
<div>
<div><label>学生姓名:</label><input type="text" id="addStudentsName"/> </div>
<div><label>学生年龄:</label><input type="text" id="addStudentsAge"/> </div>
<div>
<label>学生性别:</label>
<input type="radio" name="addStudentsGender" value="男"><label>男</label>
<input type="radio" name="addStudentsGender" value="女"><label>女</label>
</div>
<div>
<label>所属班级</label>
<select id="selectClasses">
</select>
</div>
<div>
<button id="addStudent">确认新增</button>
</div>
</div>
<h2>修改学生</h2>
<div>
<input type="hidden" id="updateStudentsId">
<div><label>学生姓名:</label><input type="text" id="updateStudentsName"/> </div>
<div><label>学生年龄:</label><input type="text" id="updateStudentsAge"/> </div>
<div>
<label>学生性别:</label>
<input type="radio" name="updateStudentsGender" value="男"><label>男</label>
<input type="radio" name="updateStudentsGender" value="女"><label>女</label>
</div>
<div>
<button id="updateStudent">确认修改</button>
</div>
</div>
<h2>查询学生</h2>
<div>
<select id="searchType">
<option value="name">姓名</option>
<option value="age">年龄</option>
<option value="gender">性别</option>
</select>
<input type="text" id="searchValue">
<button id="searchBtn">查询学生</button>
</div>
<h2>学生列表</h2>
<table>
<thead>
<tr>
<th>学生姓名</th>
<th>学生年龄</th>
<th>学生性别</th>
<th>所属班级</th>
<th>负责教师</th>
<th>学生操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>20</td>
<td>男</td>
<td>
<button>修改 | 删除</button>
</td>
</tr>
</tbody>
</table>
<div>
<label>每页条数</label>
<select id="pageSize">
<option value="2">2</option>
<option value="3">3</option>
<option value="5">5</option>
</select>
</div>
<div>
<button>首页</button>
<button id="nextPage">下一页</button>
<button id="lastPage">上一页</button>
<button>尾页</button>
</div>
<script src="./javascripts/jquery.min.js"></script>
<script>
//给一个全局变量来做查询
let data={
currentPage: 1,
pageSize: 5
}
//页面刷新就开始做这两个方法
getStudents()//获取全部学生
getClasses()//获取全部班级
getTeachers()//获取全部老师
//获取全部学生
function getStudents(){
$.ajax({
url:'/students/getStudents',
data: {
currentPage: data.currentPage,
pageSize:data.pageSize,
searchValue: data.searchValue,
searchType: data.searchType
},
type:'GET',
success(msg){
//进入if表示进入学生数据成功
if(msg.status){
data={
...data,
...msg.data
}
const str=msg.data.students.map(function (item,index) {
return `
<tr>
<td>${item.name}</td>
<td>${item.age}</td>
<td>${item.gender}</td>
<td>${item.classId.name}</td>
<td>
${
item.classId.teachersId.map(item=>`<p>${item.name}</p>`).join('')
}
</td>
<td>
<button class="updateBtn" data-id="${item._id}">修改</button>
<button class="removeBtn" data-id="${item._id}">删除</button>
</td>
</tr>
`
}).join('')//join是拼接
$('tbody').html(str)
}
}
})
}
//获取班级
function getClasses(){
$.ajax({
url:'/classes/getClasses',
type:'GET',
data:{},
success(msg){
if (msg.status){
const str=msg.data.map(function(item,index){
return `<option value="${item._id}">${item.name}</option>`
}).join('')//遍历出来data的name后,和option一起拼接成一个大字符串
$('#selectClasses').html(str)
}
}
})
}
//获取全部教师
function getTeachers(){
$.ajax({
url:'/teachers/getTeachers',
type:'GET',
success(msg){
if (msg.status){
const str=msg.data.map(item=>{
return`
<input type="checkbox" value="${item._id}"/>
<label>${item.name}</label>
`
}).join('')
$('#selectTeacher').html(str)
}
}
})
}
//新增班级
$('#addClassBtn').click(function(){
//获取选中教师的id数组,使用扩展运算符转换为真数组
const teachersId=[...$('#selectTeacher>input[type=checkbox]:checked')].map(function(item,index){
//return item.value//原生js方法
return $(item).val()//jquery方法
})
//console.log(teachersId)
$.ajax({
url:'/classes/addClasses',
type:'POST',
data:{
name:$('#addClassName').val(),
teachersId
},
//当ajax的data传递数组的时候必须要添加选项解决数组格式问题
traditional:true,
success(msg){
if (msg.status){
getClasses()
}
}
})
})
//查询下一页
$('#nextPage').click(function(){
if ( data.currentPage<data.pages){
//console.log('查看一下全局的data',data)
data.currentPage++
getStudents()
}
})
//查询上一页
$('#lastPage').click(function(){
if (data.currentPage>1){
data.currentPage--
getStudents()
}
})
//删除按钮使用事件委托
//on做委托,委托给父级的静态元素,第一个参数是事件,第二个参数是真正执行的那个标签(委托人),第三个参数是具体的工作
$('tbody').on('click','.removeBtn',function(){
//获取当前点击的这个按钮对应的id,data('id')是获取所有(特定)属性的函数,这里的id实际就是data-id,前面加data-是一种约定俗成
const _id=$(this).data('id')
console.log(_id)
$.ajax({
url:'/students/deleteStudents',
type:'post',
data: { _id },
success (msg) {
if (msg.status){
alert('删除成功')
//重新发一次ajax请求
getStudents()
}
}
})
})
//修改学生信息
//获取要修改的一个学生信息
$('tbody').on('click','.updateBtn',function(){
const _id=$(this).data('id')
//console.log(_id)
$.ajax({
url:'/students/getStudentsById',
data:{_id},
success(msg){
if (msg.status){
$('#updateStudentsId').val(msg.data._id)
$('#updateStudentsName').val(msg.data.name)//设置控件的value值
$('#updateStudentsAge').val(msg.data.age)//设置控件的value值
$(`[name=updateStudentsGender][value=${msg.data.gender}]`).prop('checked',true)
}
}
})
})
//确认修改学生信息
$('#updateStudent').click(function(){
const _id=$('#updateStudentsId').val()
const name=$('#updateStudentsName').val()
const age=$('#updateStudentsAge').val()
const gender=$(`[name=updateStudentsGender]:checked`).val()
//console.log(name,age,gender)
$.ajax({
url:'/students/updateStudents',
type:'POST',
data:{
name,age,gender,_id
},
success(msg){
if(msg.status){
getStudents()
}
}
})
})
//查询
$('#searchBtn').click(function(){
//获取下拉列表中选中的option的value值,可以直接获取selected的值
const searchType=$('#searchType').val()
//console.log(searchType)
//获取搜索的值
const searchValue=$('#searchValue').val()
data={
...data,//保留原有的data数据
searchType,
searchValue
}
//console.log(data)
getStudents()
})
//新增学生
$('#addStudent').click(function(){
const name=$('#addStudentsName').val()
const age=$('#addStudentsAge').val()
const gender=$('[name=addStudentsGender]:checked').val()
const classId=$('#selectClasses').val()
//console.log(name,age,gender)
$.ajax({
url:'/students/addStudents',
type:'POST',
data:{
name,
age,
gender,
classId
},
success(msg){
if (msg.status){
getStudents()
}
}
})
})
</script>
</body>
</html>
2、studentsDao.js
//向第二层服务层暴露getStudents方法,
//在第三层dao层操作数据库
//引入第三层dao层的model模型,用以操作数据库
const { studentsModel }=require('./models/studentsModel')
//暴露一个获取所有学生方法
module.exports.getStudents=async function ({pageSize,currentPage }) {
//获取查询的总条数
const total=await studentsModel.countDocuments()
//计算总页数
const pages=Math.ceil(total/pageSize)
//console.log('数据总条数',total)
//console.log('第三层的数据',pageSize,currentPage)
//find 是异步操作,在model里查找user记录(文档)。返回一个数组
//populate是做关联查询
const students=await studentsModel.find()
.populate({
path:'classId',
populate:{
path:'teachersId'
}
}).limit(pageSize-0)//设置请求的数据条数
.skip((currentPage-1)*pageSize)//跳过数据的条数
//console.log('第三层的data',data)
//第三层直接返回数据给第二层,不需要做任何操作,dao层-->服务层-->表现层
return {
total,
pages,
students
}
//做模糊查询
// return await studentsModel.find({
// //$options:'$i'因为不区分大小写
// [params.searchType]:{$regex:params.searchValue,$options:'$i'}
// })
}
//暴露一个获取部分学生方法
module.exports.searchStudents=async function (params) {
//做模糊查询
return await studentsModel.find({
//$options:'$i'因为不区分大小写
// [params.searchType]:{$regex:params.searchValue,$options:'$i'}
// }).populate('classId')
[params.searchType]:{$regex:params.searchValue,$options:'$i'}
}).populate( 'classId' )
}
//暴露一个新增方法
module.exports.addStudents=async function (student) {
const data=await studentsModel.create(student)
return data
}
//暴露一个删除方法
module.exports.deleteStudents=async function ({ _id }) {//这里把对象中的id解构出来了
//const data=await studentsModel.deleteOne(_id)//这里id实际是一个对象
const data=await studentsModel.findByIdAndDelete(_id)
return data
}
//暴露一个获取学生方法
module.exports.getStudentsById=async function ({ _id }) {//这里把对象中的id解构出来了
//const data=await studentsModel.deleteOne(_id)//这里id实际是一个对象
const data=await studentsModel.findById(_id)//返回的事一个对象
return data
}
//确认修改一个学生方法
module.exports.updateStudents=async function ({_id,name,age,gender }) {//这里把对象中的id解构出来了
//console.log(student)
//const data=await studentsModel.deleteOne(_id)//这里id实际是一个对象
//return await studentsModel.updateOne({_id:student._id},student)//返回的事一个对象
return await studentsModel.findByIdAndUpdate(_id, { name,age,gender})//返回的事一个对象
}
6、分页其他操作
修改index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>学生管理系统</title>
</head>
<body>
<div>
<h2>新增班级</h2>
<div>
<div>
<label>班级名称</label>
<input type="text" id="addClassName"/>
</div>
<div>
<label>选择教师</label>
<div id="selectTeacher">
<!--动态渲染教师列表-->
</div>
</div>
<button id="addClassBtn">确认新增</button>
</div>
<div><hr/></div>
</div>
<div>
<h2>新增教师</h2>
<div>
<div>
<label>教师名称</label>
<input type="text" id="addTeacherName"/>
</div>
<button id="addTeacherBtn">确认新增</button>
</div>
<div><hr/></div>
</div>
<h2>新增学生</h2>
<div>
<div><label>学生姓名:</label><input type="text" id="addStudentsName"/> </div>
<div><label>学生年龄:</label><input type="text" id="addStudentsAge"/> </div>
<div>
<label>学生性别:</label>
<input type="radio" name="addStudentsGender" value="男"><label>男</label>
<input type="radio" name="addStudentsGender" value="女"><label>女</label>
</div>
<div>
<label>所属班级</label>
<select id="selectClasses">
</select>
</div>
<div>
<button id="addStudent">确认新增</button>
</div>
</div>
<h2>修改学生</h2>
<div>
<input type="hidden" id="updateStudentsId">
<div><label>学生姓名:</label><input type="text" id="updateStudentsName"/> </div>
<div><label>学生年龄:</label><input type="text" id="updateStudentsAge"/> </div>
<div>
<label>学生性别:</label>
<input type="radio" name="updateStudentsGender" value="男"><label>男</label>
<input type="radio" name="updateStudentsGender" value="女"><label>女</label>
</div>
<div>
<button id="updateStudent">确认修改</button>
</div>
</div>
<h2>查询学生</h2>
<div>
<select id="searchType">
<option value="name">姓名</option>
<option value="age">年龄</option>
<option value="gender">性别</option>
</select>
<input type="text" id="searchValue">
<button id="searchBtn">查询学生</button>
</div>
<h2>学生列表</h2>
<table>
<thead>
<tr>
<th>学生姓名</th>
<th>学生年龄</th>
<th>学生性别</th>
<th>所属班级</th>
<th>负责教师</th>
<th>学生操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>20</td>
<td>男</td>
<td>
<button>修改 | 删除</button>
</td>
</tr>
</tbody>
</table>
<div>
<label>每页条数</label>
<select id="pageSize">
<option value="2">2</option>
<option value="3">3</option>
<option value="5">5</option>
</select>
<span><b id="currentPage">1</b>/<b id="pages">4</b>页</span><span>共计<b id="total"></b>条数据</span>
</div>
<div>
<button id="firstPage">首页</button>
<button id="nextPage">下一页</button>
<button id="lastPage">上一页</button>
<button id="finalPage">尾页</button>
</div>
<script src="./javascripts/jquery.min.js"></script>
<script>
//给一个全局变量来做查询,用来存放分页相关数据
let data={
currentPage: 1,
pageSize: 5
}
//页面刷新就开始做这两个方法
getStudents()//获取全部学生
getClasses()//获取全部班级
getTeachers()//获取全部老师
//获取全部学生
function getStudents(){
$.ajax({
url:'/students/getStudents',
data: {
currentPage: data.currentPage,
pageSize:data.pageSize,
searchValue: data.searchValue,
searchType: data.searchType
},
type:'GET',
success(msg){
//进入if表示进入学生数据成功
if(msg.status){
data={
...data,
...msg.data
}
//渲染数据
const str=msg.data.students.map(function (item,index) {
return `
<tr>
<td>${item.name}</td>
<td>${item.age}</td>
<td>${item.gender}</td>
<td>${item.classId.name}</td>
<td>
${
item.classId.teachersId.map(item=>`<p>${item.name}</p>`).join('')
}
</td>
<td>
<button class="updateBtn" data-id="${item._id}">修改</button>
<button class="removeBtn" data-id="${item._id}">删除</button>
</td>
</tr>
`
}).join('')//join是拼接
$('tbody').html(str)
//渲染下分页指示
$('#currentPage').text(data.currentPage)
$('#pages').text(data.pages)
$('#total').text(data.total)
}
}
})
}
//获取班级
function getClasses(){
$.ajax({
url:'/classes/getClasses',
type:'GET',
data:{},
success(msg){
if (msg.status){
const str=msg.data.map(function(item,index){
return `<option value="${item._id}">${item.name}</option>`
}).join('')//遍历出来data的name后,和option一起拼接成一个大字符串
$('#selectClasses').html(str)
}
}
})
}
//获取全部教师
function getTeachers(){
$.ajax({
url:'/teachers/getTeachers',
type:'GET',
success(msg){
if (msg.status){
const str=msg.data.map(item=>{
return`
<input type="checkbox" value="${item._id}"/>
<label>${item.name}</label>
`
}).join('')
$('#selectTeacher').html(str)
}
}
})
}
//新增班级
$('#addClassBtn').click(function(){
//获取选中教师的id数组,使用扩展运算符转换为真数组
const teachersId=[...$('#selectTeacher>input[type=checkbox]:checked')].map(function(item,index){
//return item.value//原生js方法
return $(item).val()//jquery方法
})
//console.log(teachersId)
$.ajax({
url:'/classes/addClasses',
type:'POST',
data:{
name:$('#addClassName').val(),
teachersId
},
//当ajax的data传递数组的时候必须要添加选项解决数组格式问题
traditional:true,
success(msg){
if (msg.status){
getClasses()
}
}
})
})
//查询下一页
$('#nextPage').click(function(){
if ( data.currentPage<data.pages){
//console.log('查看一下全局的data',data)
data.currentPage++
getStudents()
}
})
//查询上一页
$('#lastPage').click(function(){
if (data.currentPage>1){
data.currentPage--
getStudents()
}
})
//查询首页
$('#firstPage').click(function(){
data.currentPage=1
getStudents()
})
//查询尾页
$('#finalPage').click(function(){
data.currentPage=data.pages
getStudents()
})
//删除按钮使用事件委托
//on做委托,委托给父级的静态元素,第一个参数是事件,第二个参数是真正执行的那个标签(委托人),第三个参数是具体的工作
$('tbody').on('click','.removeBtn',function(){
//获取当前点击的这个按钮对应的id,data('id')是获取所有(特定)属性的函数,这里的id实际就是data-id,前面加data-是一种约定俗成
const _id=$(this).data('id')
console.log(_id)
$.ajax({
url:'/students/deleteStudents',
type:'post',
data: { _id },
success (msg) {
if (msg.status){
alert('删除成功')
data.currentPage=1
//重新发一次ajax请求
getStudents()
}
}
})
})
//修改学生信息
//获取要修改的一个学生信息
$('tbody').on('click','.updateBtn',function(){
const _id=$(this).data('id')
//console.log(_id)
$.ajax({
url:'/students/getStudentsById',
data:{_id},
success(msg){
if (msg.status){
$('#updateStudentsId').val(msg.data._id)
$('#updateStudentsName').val(msg.data.name)//设置控件的value值
$('#updateStudentsAge').val(msg.data.age)//设置控件的value值
$(`[name=updateStudentsGender][value=${msg.data.gender}]`).prop('checked',true)
}
}
})
})
//确认修改学生信息
$('#updateStudent').click(function(){
const _id=$('#updateStudentsId').val()
const name=$('#updateStudentsName').val()
const age=$('#updateStudentsAge').val()
const gender=$(`[name=updateStudentsGender]:checked`).val()
//console.log(name,age,gender)
$.ajax({
url:'/students/updateStudents',
type:'POST',
data:{
name,age,gender,_id
},
success(msg){
if(msg.status){
getStudents()
}
}
})
})
//查询
$('#searchBtn').click(function(){
//获取下拉列表中选中的option的value值,可以直接获取selected的值
const searchType=$('#searchType').val()
//console.log(searchType)
//获取搜索的值
const searchValue=$('#searchValue').val()
data={
...data,//保留原有的data数据
searchType,
searchValue
}
//console.log(data)
getStudents()
})
//新增学生
$('#addStudent').click(function(){
const name=$('#addStudentsName').val()
const age=$('#addStudentsAge').val()
const gender=$('[name=addStudentsGender]:checked').val()
const classId=$('#selectClasses').val()
//console.log(name,age,gender)
$.ajax({
url:'/students/addStudents',
type:'POST',
data:{
name,
age,
gender,
classId
},
success(msg){
if (msg.status){
getStudents()
}
}
})
})
</script>
</body>
</html>
7、分页后的搜索功能优化
调整太多……主要是分页上的几个按钮及对应是事件处理函数
1、index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="stylesheets/index.css">
<title>学生管理系统</title>
</head>
<body>
<div>
<h2>新增班级</h2>
<div>
<div>
<label>班级名称</label>
<input type="text" id="addClassName"/>
</div>
<div>
<label>选择教师</label>
<div id="selectTeacher">
<!--动态渲染教师列表-->
</div>
</div>
<button id="addClassBtn">确认新增</button>
</div>
<div><hr/></div>
</div>
<div>
<h2>新增教师</h2>
<div>
<div>
<label>教师名称</label>
<input type="text" id="addTeacherName"/>
</div>
<button id="addTeacherBtn">确认新增</button>
</div>
<div><hr/></div>
</div>
<h2>新增学生</h2>
<div>
<div><label>学生姓名:</label><input type="text" id="addStudentsName"/> </div>
<div><label>学生年龄:</label><input type="text" id="addStudentsAge"/> </div>
<div>
<label>学生性别:</label>
<input type="radio" name="addStudentsGender" value="男"><label>男</label>
<input type="radio" name="addStudentsGender" value="女"><label>女</label>
</div>
<div>
<label>所属班级</label>
<select id="selectClasses">
</select>
</div>
<div>
<label>上传头像</label>
<input type="file">
</div>
<div class="imag-box">
<!-- 显示图片预览 -->
<img src="" alt=""/>
</div>
<div>
<button id="addStudent">确认新增</button>
</div>
</div>
<h2>修改学生</h2>
<div>
<input type="hidden" id="updateStudentsId">
<div><label>学生姓名:</label><input type="text" id="updateStudentsName"/> </div>
<div><label>学生年龄:</label><input type="text" id="updateStudentsAge"/> </div>
<div>
<label>学生性别:</label>
<input type="radio" name="updateStudentsGender" value="男"><label>男</label>
<input type="radio" name="updateStudentsGender" value="女"><label>女</label>
</div>
<div>
<button id="updateStudent">确认修改</button>
</div>
</div>
<h2>查询学生</h2>
<div>
<select id="searchType">
<option value="name">姓名</option>
<option value="age">年龄</option>
<option value="gender">性别</option>
</select>
<input type="text" id="searchValue">
<button id="searchBtn">查询学生</button>
</div>
<h2>学生列表</h2>
<table>
<thead>
<tr>
<th>学生姓名</th>
<th>学生年龄</th>
<th>学生性别</th>
<th>所属班级</th>
<th>负责教师</th>
<th>学生操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>20</td>
<td>男</td>
<td>
<button>修改 | 删除</button>
</td>
</tr>
</tbody>
</table>
<div>
<label>每页条数</label>
<select id="pageSize">
<option value="2">2</option>
<option value="3">3</option>
<option value="5">5</option>
</select>
<span><b id="currentPage">1</b>/<b id="pages">4</b>页</span><span>共计<b id="total"></b>条数据</span>
</div>
<div>
<button id="firstPage">首页</button>
<button id="nextPage">下一页</button>
<button id="lastPage">上一页</button>
<button id="finalPage">尾页</button>
</div>
<script src="./javascripts/jquery.min.js"></script>
<script>
//给一个全局变量来做查询,用来存放分页相关数据
let data={
currentPage: 1,
pageSize: 5
}
//页面刷新就开始做这两个方法
getStudents()//获取全部学生
getClasses()//获取全部班级
getTeachers()//获取全部老师
//获取全部学生
function getStudents(){
$.ajax({
url:'/students/getStudents',
data: {
currentPage: data.currentPage,
pageSize:data.pageSize,
searchValue: data.searchValue,
searchType: data.searchType
},
type:'GET',
success(msg){
//进入if表示进入学生数据成功
if(msg.status){
data={
...data,
...msg.data
}
console.log(msg.data)
//渲染数据
const str=msg.data.students.map(function (item,index) {
return `
<tr>
<td>${item.name}</td>
<td>${item.age}</td>
<td>${item.gender}</td>
<td>${item.classId.name}</td>
<td>
${
item.classId.teachersId.map(item=>`<p>${item.name}</p>`).join('')
}
</td>
<td>
<button class="updateBtn" data-id="${item._id}">修改</button>
<button class="removeBtn" data-id="${item._id}">删除</button>
</td>
</tr>
`
}).join('')//join是拼接
$('tbody').html(str)
//渲染下分页指示
$('#currentPage').text(data.currentPage)
$('#pages').text(data.pages)
$('#total').text(data.total)
}
}
})
}
//获取班级
function getClasses(){
$.ajax({
url:'/classes/getClasses',
type:'GET',
data:{},
success(msg){
if (msg.status){
const str=msg.data.map(function(item,index){
return `<option value="${item._id}">${item.name}</option>`
}).join('')//遍历出来data的name后,和option一起拼接成一个大字符串
$('#selectClasses').html(str)
}
}
})
}
//获取全部教师
function getTeachers(){
$.ajax({
url:'/teachers/getTeachers',
type:'GET',
success(msg){
if (msg.status){
const str=msg.data.map(item=>{
return`
<input type="checkbox" value="${item._id}"/>
<label>${item.name}</label>
`
}).join('')
$('#selectTeacher').html(str)
}
}
})
}
//新增班级
$('#addClassBtn').click(function(){
//获取选中教师的id数组,使用扩展运算符转换为真数组
const teachersId=[...$('#selectTeacher>input[type=checkbox]:checked')].map(function(item,index){
//return item.value//原生js方法
return $(item).val()//jquery方法
})
//console.log(teachersId)
$.ajax({
url:'/classes/addClasses',
type:'POST',
data:{
name:$('#addClassName').val(),
teachersId
},
//当ajax的data传递数组的时候必须要添加选项解决数组格式问题
traditional:true,
success(msg){
if (msg.status){
getClasses()
}
}
})
})
//查询下一页
$('#nextPage').click(function(){
if ( data.currentPage<data.pages){
//console.log('查看一下全局的data',data)
data.currentPage++
getStudents()
}
})
//查询上一页
$('#lastPage').click(function(){
if (data.currentPage>1){
data.currentPage--
getStudents()
}
})
//查询首页
$('#firstPage').click(function(){
data.currentPage=1
getStudents()
})
//查询尾页
$('#finalPage').click(function(){
data.currentPage=data.pages
getStudents()
})
//设置每页条数
$('#pageSize').change(function(){
data.pageSize=$('#pageSize').val()
data.currentPage=1
getStudents()
})
//删除按钮使用事件委托
//on做委托,委托给父级的静态元素,第一个参数是事件,第二个参数是真正执行的那个标签(委托人),第三个参数是具体的工作
$('tbody').on('click','.removeBtn',function(){
//获取当前点击的这个按钮对应的id,data('id')是获取所有(特定)属性的函数,这里的id实际就是data-id,前面加data-是一种约定俗成
const _id=$(this).data('id')
console.log(_id)
$.ajax({
url:'/students/deleteStudents',
type:'post',
data: { _id },
success (msg) {
if (msg.status){
alert('删除成功')
data.currentPage=1
//重新发一次ajax请求
getStudents()
}
}
})
})
//修改学生信息
//获取要修改的一个学生信息
$('tbody').on('click','.updateBtn',function(){
const _id=$(this).data('id')
//console.log(_id)
$.ajax({
url:'/students/getStudentsById',
data:{_id},
success(msg){
if (msg.status){
$('#updateStudentsId').val(msg.data._id)
$('#updateStudentsName').val(msg.data.name)//设置控件的value值
$('#updateStudentsAge').val(msg.data.age)//设置控件的value值
$(`[name=updateStudentsGender][value=${msg.data.gender}]`).prop('checked',true)
}
}
})
})
//确认修改学生信息
$('#updateStudent').click(function(){
const _id=$('#updateStudentsId').val()
const name=$('#updateStudentsName').val()
const age=$('#updateStudentsAge').val()
const gender=$(`[name=updateStudentsGender]:checked`).val()
//console.log(name,age,gender)
$.ajax({
url:'/students/updateStudents',
type:'POST',
data:{
name,age,gender,_id
},
success(msg){
if(msg.status){
getStudents()
}
}
})
})
//查询
$('#searchBtn').click(function(){
//获取下拉列表中选中的option的value值,可以直接获取selected的值
const searchType=$('#searchType').val()
//console.log(searchType)
//获取搜索的值
const searchValue=$('#searchValue').val()
data={
...data,//保留原有的data数据
currentPage: 1,
searchType,
searchValue
}
//console.log(data)
getStudents()
})
//新增学生
$('#addStudent').click(function(){
const name=$('#addStudentsName').val()
const age=$('#addStudentsAge').val()
const gender=$('[name=addStudentsGender]:checked').val()
const classId=$('#selectClasses').val()
//console.log(name,age,gender)
$.ajax({
url:'/students/addStudents',
type:'POST',
data:{
name,
age,
gender,
classId
},
success(msg){
if (msg.status){
getStudents()
}
}
})
})
</script>
</body>
</html>
2、studentsDao.js
主要是接个页数,条数,查询到的条数和页数的计算
//向第二层服务层暴露getStudents方法,
//在第三层dao层操作数据库
//引入第三层dao层的model模型,用以操作数据库
const { studentsModel }=require('./models/studentsModel')
//暴露一个获取所有学生方法
module.exports.getStudents=async function ({pageSize,currentPage }) {
//获取查询的总条数
const total=await studentsModel.countDocuments()
//计算总页数
const pages=Math.ceil(total/pageSize)
//console.log('数据总条数',total)
//console.log('第三层的数据',pageSize,currentPage)
//find 是异步操作,在model里查找user记录(文档)。返回一个数组
//populate是做关联查询
const students=await studentsModel.find()
.populate({
path:'classId',
populate:{
path:'teachersId'
}
}).limit(pageSize-0)//设置请求的数据条数
.skip((currentPage-1)*pageSize)//跳过数据的条数
//console.log('第三层的data',data)
//第三层直接返回数据给第二层,不需要做任何操作,dao层-->服务层-->表现层
return {
total,
pages,
students
}
//做模糊查询
// return await studentsModel.find({
// //$options:'$i'因为不区分大小写
// [params.searchType]:{$regex:params.searchValue,$options:'$i'}
// })
}
//暴露一个获取部分学生方法
module.exports.searchStudents=async function (params) {
//获取查询到的数据总条数
const total=await studentsModel.find({
[params.searchType]:{$regex:params.searchValue,$options:'$i'}
}).countDocuments(true)
console.log('查询出来的总条数',total)
//获取查询到的总页数
const pages=Math.ceil(total/params.pageSize)
//做模糊查询
const students= await studentsModel.find({
//$options:'$i'因为不区分大小写
// [params.searchType]:{$regex:params.searchValue,$options:'$i'}
// }).populate('classId')
[params.searchType]:{$regex:params.searchValue,$options:'$i'}
}).populate({
path:'classId',
populate:{
path:'teachersId'
}
}).limit(params.pageSize-0)
.skip((params.currentPage-1)*params.pageSize)
return {
students,
pages,
total
}
}
//暴露一个新增方法
module.exports.addStudents=async function (student) {
const data=await studentsModel.create(student)
return data
}
//暴露一个删除方法
module.exports.deleteStudents=async function ({ _id }) {//这里把对象中的id解构出来了
//const data=await studentsModel.deleteOne(_id)//这里id实际是一个对象
const data=await studentsModel.findByIdAndDelete(_id)
return data
}
//暴露一个获取学生方法
module.exports.getStudentsById=async function ({ _id }) {//这里把对象中的id解构出来了
//const data=await studentsModel.deleteOne(_id)//这里id实际是一个对象
const data=await studentsModel.findById(_id)//返回的事一个对象
return data
}
//确认修改一个学生方法
module.exports.updateStudents=async function ({_id,name,age,gender }) {//这里把对象中的id解构出来了
//console.log(student)
//const data=await studentsModel.deleteOne(_id)//这里id实际是一个对象
//return await studentsModel.updateOne({_id:student._id},student)//返回的事一个对象
return await studentsModel.findByIdAndUpdate(_id, { name,age,gender})//返回的事一个对象
}