八、学员管理-列表查询、分页、搜索

一、先把学员数据渲染到页面

1.新创建学生的一个数据库,在服务器创建一个student.js和数据库进行连接,创建一些规则:

const mongoose = require('mongoose')

mongoose.connect('mongodb://localhost/test') //和test数据库创建连接

module.exports = mongoose.model('Student', { //数据库的规则
    stunum: { //学号
        type: String,
        required: true
    },
    name: { //姓名
        type: String,
        required: true
    },
    admissiondate: { //入学日期
        type: String,
        required: true
    },
    phone: { //电话号
        type: String,
        required: true
    },
    teacher: { //授课教师
        type: String,
        required: true
    },
    class: { //班级
        type: String,
            required: true
    },
    hobby: { //爱好
        type: String,
    },
    commonSaying: { //口头禅
        type: String,
    }
})

2. 然后在数据库中添加数据:

mongo

use 数据库名称

db.createCollection("students")

db.students.insert([{'stunum':'001','name':'小新','admissiondate':'2015-11-11','phone':'12454686898','teacher':'吉永','class':'向日葵小班','hobby':'看动感超人','commonSaying':'嘿嘿 这没什么啦'},{'stunum':'002','name':'妮妮','admissiondate':'2015-11-11','phone':'12454686898','teacher':'吉永','class':'向日葵小班','hobby':'扮家家酒','commonSaying':'讨厌'},{'stunum':'003','name':'风间','admissiondate':'2015-11-11','phone':'12454686898','teacher':'吉永','class':'向日葵小班','hobby':'大概是读书吧','commonSaying':'小新!!'},{'stunum':'004','name':'阿呆','admissiondate':'2015-11-11','phone':'12454686898','teacher':'吉永','class':'向日葵小班','hobby':'收集石头','commonSaying':' '},{'stunum':'005','name':'正南','admissiondate':'2015-11-11','phone':'12454686898','teacher':'吉永','class':'向日葵小班','hobby':'小爱','commonSaying':'啊'}])

db.students.find()

3.然后把数据引入到router.js当中,让路由管理:

let Student = require('./student.js')

4.然后去学生组件把主体复制过去,并修改一下,作为学生组件的界面:

<template>
    <div>
        <h1>学生</h1>
        <!-- 学生列表 -->
        <el-table :data="studentTableData" height="400" border style="width: 100%">
            <el-table-column type="index" label="序号"> </el-table-column>
            <el-table-column prop="stunum" label="学号"> </el-table-column>
            <el-table-column prop="name" label="姓名"> </el-table-column>
            <el-table-column prop="admissiondate" label="入学时间"> </el-table-column>
            <el-table-column prop="phone" label="电话"> </el-table-column>
            <el-table-column prop="teacher" label="授课教师"> </el-table-column>
            <el-table-column prop="class" label="班级"> </el-table-column>
            <el-table-column prop="hobby" label="爱好"> </el-table-column>
            <el-table-column prop="commonSaying" label="口头禅"> </el-table-column>
            <el-table-column label="操作">
                <template slot-scope="scope">
                    <el-button size="mini" @click="handleEdit(scope.row._id)">编辑</el-button>
                    <el-button size="mini" type="danger" @click="handleDelete(scope.row._id)">删除</el-button>
                </template>
            </el-table-column>
        </el-table>
    </div>
</template>

5.并把相应方法在下面创建出来:

<script>
export default {
    name: "Student",
    data() {
        return {
            studentTableData: [],
        };
    },
    methods: {
        handleEdit() { },
        handleDelete() { },
    }
}
</script>

6.然后回后台服务器把接口写出来,这个和教师接口一样啦,这里是一个接口多用,既能拿到学生列表,又可以分页,还能按条件查询,由于这里不传参时,直接能拿到学生列表,我们先把学生的数据展示出来:

// 学生列表
router.post("/student/list", (req, res) => {
    let page = req.body.page || 1; //页数
    let size = req.body.size || 10; //一页显示多少条
    let searchMap = req.body.searchMap || {}
        // console.log(page, size, searchMap);
    let obj = {}
    searchMap.jobnumber ? obj["jobnumber"] = searchMap.jobnumber : obj
    searchMap.name ? obj["name"] = searchMap.name : obj
    searchMap.role ? obj["role"] = searchMap.role : obj
    searchMap.entrydate ? obj["entrydate"] = searchMap.entrydate : obj

    Student.find(obj, (err, data) => {
        if (err) {
            return res.status(500).json({
                code: 3000,
                flag: false,
                message: "服务器后台错误"
            })
        }
        let content = data.length

        //skip跳过多少条,limit查询多少个,exec当前面的代码,执行完毕后,产生的回调
        Student.find(obj).skip((page - 1) * parseInt(size)).limit(parseInt(size)).exec((err, data) => {
            if (err) {
                return res.status(500).json({
                    code: 3000,
                    flag: false,
                    message: "服务器后台错误"
                })
            }
            return res.status(200).json({
                "code": 2000,
                "flag": true,
                "message": "查询成功",
                "data": {
                    content,
                    "rows": data
                }
            })
        })
    })

})

7.然后再前台的api中创建一个student.js,这次我们用默认导出的方式:

import request from "@/utils/request";

// 这里采用默认导出的方式:
export default {
    getStuList() {//获得学生列表
        return request({
            url: "/student/listPage",
            method: "post",
        })
    }
}

8.然后要在学生组件中,把student.js引入进来:

import studentApi from "@/api/student.js";

9.创建stuList()方法,渲染数据:

<script>
import studentApi from '@/api/student';
export default {
    name: "Student",
    data() {
        return {
            studentTableData: [],
        };
    },
    created() {
        this.stuList()
    },
    methods: {
        // 获得学生列表
        stuList() {
            studentApi.getStuList().then(res => {
                console.log(res);
                this.studentTableData = res.data.data.rows
            }).catch()
        },
        handleEdit() { },
        handleDelete() { },
    }
}
</script>

10.在created中使用一下:

created () {
    this.getList()
  }

11.此时,页面信息被渲染到页面了。

 

二、分页

1.先把分页模板在学生组件中写出来:

   <!-- 分页区 -->
        <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage"
            :page-sizes="pageSizes" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total">
        </el-pagination>

2.在data中,把数据添加上去:

 data() {
        return {
            // 学生列表
            studentTableData: [],
            // 分页
            currentPage: 1,//当前页数
            pageSize: 5,//每页显示多少条数据
            pageSizes: [5, 10, 15, 20],// 每页显示个数选择器的选项设置
            total: 0,
        };
    },

 3.并把相应方法在下面创建出来:

     //element-ui 的控制表格方法
        handleSizeChange(val) {
            this.pageSize = val;
            this.stuList()
        },
        //element-ui 的控制表格方法
        handleCurrentChange(val) {
            this.currentPage = val;
            this.stuList()
        },

4.现在分页模板能渲染到页面中了,接下来,我们把数据给分页传过去,在api/student.js中,添加:

import request from "@/utils/request";

// 这里采用默认导出的方式:
export default {
    getStuList(page, size) { //获得学生列表
        return request({
            url: "/student/listPage",
            method: "post",
            data: {
                page,
                size
            }
        })
    }
}

5.再回到学生组件,把数据渲染到页面:

  // 获得学生列表
        stuList() {
            studentApi.getStuList(this.currentPage, this.pageSize).then(res => {
                console.log(res);
                let resArr = res.data
                this.total = resArr.data.content
                this.studentTableData = resArr.data.rows
            }).catch(err => {
                console.log(err);
            })
        },

6.现在分页的所有功能就实现了。

三、条件查询实现

在列表上方添加查询功能,通过 学号 、学员姓名、授课教师等条件查询

1. 修改 src\views\student\index.vue ,增加条件查询模板代码:

 <!-- 搜索区 -->
        <el-form :inline="true" :model="searchMap" ref="searchForm" class="demo-form-inline">
            <!-- prop 表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的 -->
            <el-form-item label="学号" prop="stunum">
                <el-input v-model="searchMap.stunum" placeholder="学号"></el-input>
            </el-form-item>
            <el-form-item label="姓名" prop="name">
                <el-input v-model="searchMap.name" placeholder="姓名"></el-input>
            </el-form-item>
            <el-form-item label="授课教师" prop="teacher">
                <el-input v-model="searchMap.teacher" placeholder="授课教师"></el-input>
            </el-form-item>
            <el-form-item label="入学时间" prop="admissiondate">
                <el-date-picker type="date" placeholder="选择日期" value-format="yyyy-MM-dd"
                    v-model="searchMap.admissiondate"></el-date-picker>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="onSubmit">查询</el-button>
                <el-button @click="resetForm('searchForm')">重置</el-button>
                <el-button type="text" @click="addMember">新增</el-button>
            </el-form-item>
        </el-form>

data 选项中的searchMap对象中指定条件字段:

 data() {
        return {
            // 学生列表
            studentTableData: [],
            // 分页
            currentPage: 1,//当前页数
            pageSize: 5,//每页显示多少条数据
            pageSizes: [5, 10, 15, 20],// 每页显示个数选择器的选项设置
            total: 0,
            // 搜索栏
            searchMap: {
                stunum: '',
                name: '',
                teacher: '',
                admissiondate: ''
            }
        };
    },

 为了页面不报错,也先把相应方法在methods里创建出来:

        // 查询
        onSubmit() {
            // 点击查询,重新分页并获取学生列表
            this.currentPage = 1;
            this.stuList()
        },
        //element-ui 的重置方法
        resetForm(formName) {
            this.$refs[formName].resetFields();
            // 点击查询,重新分页并获取学生列表
            this.currentPage = 1;
            this.stuList()
        },
        // 新增
        addMember() { },

 为了点击查询时,把要查询的数据发送到后台当中,所以回到api下的students.js里和学生组件的stuList()里把searchMap传过去:

import request from "@/utils/request";

// 这里采用默认导出的方式:
export default {
    getStuList(page, size,searchMap) { //获得学生列表
        return request({
            url: "/student/listPage",
            method: "post",
            data: {
                page,
                size,
                searchMap
            }
        })
    }
}
// 获得学生列表
        stuList() {
            studentApi.getStuList(this.currentPage, this.pageSize,this.searchMap).then(res => {
                console.log(res);
                let resArr = res.data
                this.total = resArr.data.content
                this.studentTableData = resArr.data.rows
            }).catch(err => {
                console.log(err);
            })
        },

再回到服务器后台里,改掉数据:

    searchMap.stunum ? obj["stunum"] = searchMap.stunum : obj
    searchMap.name ? obj["name"] = searchMap.name : obj
    searchMap.teacher ? obj["teacher"] = searchMap.teacher : obj
    searchMap.admissiondate ? obj["admissiondate"] = searchMap.admissiondate : obj
// 分页// 学生列表
router.post("/student/listPage", (req, res) => {
    let page = req.body.page || 1; //页数
    let size = req.body.size || 10; //一页显示多少条
    let searchMap = req.body.searchMap || {} //用来做条件查询的
        // console.log(page, size, searchMap);
    let obj = {} //用来接收搜索栏数据,实现按条件查询
        // searchMap中是否包含jobnumber、name、role、entrydate,如果有,把他们存到obj里
    searchMap.stunum ? obj["stunum"] = searchMap.stunum : obj
    searchMap.name ? obj["name"] = searchMap.name : obj
    searchMap.teacher ? obj["teacher"] = searchMap.teacher : obj
    searchMap.admissiondate ? obj["admissiondate"] = searchMap.admissiondate : obj
        // console.log(searchMap, obj);
    Student.find(obj).then((data, err) => { //去数据库中查找
        if (err) {
            return res.status(500).json({
                code: 3000,
                flag: false,
                message: "服务器后台错误"
            })
        }
        let content = data.length

        //skip跳过多少条,limit查询多少个,exec当前面的代码,执行完毕后,产生的回调
        Student.find(obj).skip((page - 1) * parseInt(size)).limit(parseInt(size)).exec().then((data, err) => {
            console.log(obj, page, size, data);
            if (err) {
                return res.status(500).json({
                    code: 3000,
                    flag: false,
                    message: "服务器后台错误"
                })
            }
            return res.status(200).json({
                "code": 2000,
                "flag": true,
                "message": "查询成功",
                "data": {
                    content,
                    "rows": data
                }
            })
        })
    })
})

测试:查询成功!重置成功!

2. 授课教师选择

效果是:点击输入框,弹出一个对话框,对话框里直接复用教师管理组件,

2.1. 将 teacher\index.vue 导入 student\index.vue 作为子组件使用。注意: components 记得注册 Teacher作为子组件

import Teacher from "../teacher/index.vue";//1.先引入
 
 
export default {
  components: {//2.在这里注册
    Teacher//作为子组件传过来
  },}

2.2使用 dialog 对话框组件,包裹 Teacher 组件:

  <!-- 弹出教师组件 -->
        <el-dialog title="请选择教师" :visible.sync="dialogFormVisible">
            <Teacher :isDialog="isDialog" />
            <div slot="footer" class="dialog-footer">
                <el-button @click="dialogFormVisible = false">取 消</el-button>
                <el-button type="primary" @click="dialogFormVisible = false">确 定</el-button>
            </div>
        </el-dialog>

 2.3在 student\index.vue 组件的 data 选项中定义 dialogFormVisible控制对话框 

          // 控制教师组件弹出的
            dialogFormVisible: false,

2.4. 设置当点击输入框时,弹出框才弹出,@click.native 点击事件。注意: el-input 是组件,要在组件元素监听原生事件,需要使用 v-on:原生事件名.native="处理函数",readonly 只读框 :

<el-form-item label="授课教师" prop="teacher">
                <el-input v-model="searchMap.teacher" placeholder="授课教师" @click.native="dialogFormVisible = true" readonly></el-input>
</el-form-item>

2.5教师页面在弹出时候很多是我们不需要的, 进行优化,父组件student向子组件teacher传递数据: 子组件通过 props 声明接收,向教师 Teacher 子组件传入一个参数 isDialog , 如果是弹出窗口, 则弹出页面隐藏一些功能. (我们自定义一个属性,isDialog,让它的布尔值来决定他是否隐藏)在 student\index.vue 上的 组件data标签上绑定属性 :isDialog="true":
 

  data() {
        return {
            // 学生列表
            studentTableData: [],
            // 分页
            currentPage: 1,//当前页数
            pageSize: 5,//每页显示多少条数据
            pageSizes: [5, 10, 15, 20],// 每页显示个数选择器的选项设置
            total: 0,
            // 搜索栏
            searchMap: {
                stunum: '',
                name: '',
                teacher: '',
                admissiondate: ''
            },
            // 控制教师组件弹出的
            dialogFormVisible: false,
            // 控制教师组件有些内容是否显示的
            isDialog: true,
        };
    },
  <!-- 弹出教师组件 -->
        <el-dialog title="请选择教师" :visible.sync="dialogFormVisible">
            <Teacher :isDialog="isDialog" />
            <div slot="footer" class="dialog-footer">
                <el-button @click="dialogFormVisible = false">取 消</el-button>
                <el-button type="primary" @click="dialogFormVisible = false">确 定</el-button>
            </div>
        </el-dialog>

子组件接收:

export default {
    name: "Teacher",
    props: {
        isDialog: Boolean
    },
    ....
}

采用 v-if=“!isDialog” 来隐藏,在子组件中:

搜索区添加v-if=“!isDialog”:

 <!-- 搜索区 -->
        <el-form :inline="true" :model="searchMap" ref="searchForm" class="demo-form-inline" v-if="!isDialog">
            <!-- prop 表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的 -->
            <el-form-item label="工号" prop="jobnumber">
                <el-input v-model="searchMap.jobnumber" placeholder="工号"></el-input>
            </el-form-item>
            <el-form-item label="姓名" prop="name">
                <el-input v-model="searchMap.name" placeholder="姓名"></el-input>
            </el-form-item>
            <el-form-item label="职务" prop="role">
                <el-select v-model="searchMap.role" placeholder="职务">
                    <el-option :key="index" v-for="(item, index) in roleOptions" :label="item.name"
                        :value="item.type"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="入职时间" prop="entrydate">
                <el-date-picker type="date" placeholder="选择日期" value-format="yyyy-MM-dd"
                    v-model="searchMap.entrydate"></el-date-picker>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="onSubmit">查询</el-button>
                <el-button @click="resetForm('searchForm')">重置</el-button>
                <el-button type="text" @click="addMember">新增</el-button>
            </el-form-item>
        </el-form>

教师列表添加v-if=“!isDialog”:

 <!-- 教师列表 -->
        <el-table :data="teacherTableData" height="400" border style="width: 100%">
            <el-table-column type="index" label="序号" v-if="!isDialog"> </el-table-column>
            <el-table-column prop="jobnumber" label="工号" v-if="!isDialog"> </el-table-column>
            <el-table-column prop="name" label="姓名"> </el-table-column>
            <el-table-column prop="role" label="职务">
                <template slot-scope="scope">
                    <span style="margin-left: 10px">{{ scope.row.role | roleFilter }}</span>
                </template>
            </el-table-column>
            <el-table-column prop="entrydate" label="入职时间" v-if="!isDialog"> </el-table-column>
            <el-table-column prop="phone" label="电话"> </el-table-column>
            <el-table-column label="操作" v-if="!isDialog">
                <template slot-scope="scope">
                    <el-button size="mini" @click="handleEdit(scope.row._id)">编辑</el-button>
                    <el-button size="mini" type="danger" @click="handleDelete(scope.row._id)">删除</el-button>
                </template>
            </el-table-column>
        </el-table>

分页区:

  <!-- 分页区 -->
        <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage"
            :page-sizes="pageSizes" :page-size="pageSize"
            :layout="!isDialog ? 'total, sizes, prev, pager, next, jumper' : ' prev, pager, next'" :total="total">
        </el-pagination>

最终效果:

 

2.6. 现在要实现:当点击子组件列表中某一行教师,即选中;选中的那个教师名字出现在父组件学员管理 的授课教师输入框中 

在 teacher\index.vue 组件的 el-table 表格组件上配置 @current-change="getTeacherName":

 <!-- 教师列表 -->
        <!-- @current-change 点击某一行,拿到这一行的数据 -->
        <el-table :data="teacherTableData" height="400" border style="width: 100%" @current-change="getTeacherName">
            <el-table-column type="index" label="序号" v-if="!isDialog"> </el-table-column>
            <el-table-column prop="jobnumber" label="工号" v-if="!isDialog"> </el-table-column>
            <el-table-column prop="name" label="姓名"> </el-table-column>
            <el-table-column prop="role" label="职务">
                <template slot-scope="scope">
                    <span style="margin-left: 10px">{{ scope.row.role | roleFilter }}</span>
                </template>
            </el-table-column>
            <el-table-column prop="entrydate" label="入职时间" v-if="!isDialog"> </el-table-column>
            <el-table-column prop="phone" label="电话"> </el-table-column>
            <el-table-column label="操作" v-if="!isDialog">
                <template slot-scope="scope">
                    <el-button size="mini" @click="handleEdit(scope.row._id)">编辑</el-button>
                    <el-button size="mini" type="danger" @click="handleDelete(scope.row._id)">删除</el-button>
                </template>
            </el-table-column>
        </el-table>

在 teacher\index.vue 组件定义 getTeacherName函数,向父组件传递点击数据。(子组件向父组件传递数据:通过 $emit 触发事件的方式 ):

        // 向父组件传name
        getTeacherName(val) {
            this.$emit("get-teacher-name",val)
        },

在父组件 student\index.vue中监听自定义事件 get-teacher-name:

<Teacher :isDialog="isDialog" @get-teacher-name="handleTName"/>

在父组件student\index.vue中添加 事件触发的函数handleTName进行回显数据:

 // 得到子组件数据:教师名字
        handleTName(val) {
            this.searchMap.teacher = val.name;//数据回显到授课教师输入框内
            this.dialogFormVisible = false//关闭窗口
        },

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值