六、教师管理-列表查询、分页、搜索

一、 需求分析

教师管理主要针对充值教师进行管理,首先开发教师管理模块中的列表功能,包含条件查询、下拉框、日期功能、 数据列表、分页。

二、 教师数据列表

1 nodejs 添加数据列表接口,去node文件,在创建一个teacher.js,创建教师的一个规则

const mongoose = require('mongoose')

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

module.exports = mongoose.model('Teacher', { //数据库的规则
    jobnumber: {
        type: String,
        required: true
    },
    name: {
        type: String,
        required: true
    },
    role: {
        type: String,
        required: true
    },
    entrydate: {
        type: String,
        required: true
    },
    phone: {
        type: String,
        required: true
    }
})

2.让路由管理一下他,在router.js中引入

let Teacher = require('./teacher.js')

3.然后在下面写一个接口,在这之前,先把数据存到数据库中,创建出Teacher这个表,打开mongoose

mongo

use 数据库名称

db.createCollection("teachers")

2(教师) 1(班主任)
工号    姓名    职务    入职时间        电话

db.teachers.insert([{'jobnumber':'001','name':'申秀莲','role':'1','entrydate':'2015-11-11','phone':'15022221111'},{'jobnumber':'002','name':'周蛋挞','role':'1','entrydate':'2015-11-11','phone':'15022221111'},{'jobnumber':'003','name':'千瑞珍','role':'2','entrydate':'2015-11-11','phone':'15022221111'},{'jobnumber':'004','name':'吴允熙','role':'2','entrydate':'2015-11-11','phone':'15022221111'},{'jobnumber':'005','name':'夏博士','role':'1','entrydate':'2015-11-11','phone':'15022221111'},{'jobnumber':'006','name':'杨狗蛋','role':'1','entrydate':'2015-11-11','phone':'15022221111'},{'jobnumber':'007','name':'麻辣烫','role':'1','entrydate':'2015-11-11','phone':'15022221111'},{'jobnumber':'008','name':'闵雪雅','role':'1','entrydate':'2015-11-11','phone':'15022221111'},{'jobnumber':'009','name':'周锡京','role':'2','entrydate':'2015-11-11','phone':'15022221111'},{'jobnumber':'0010','name':'夏恩星','role':'1','entrydate':'2015-11-11','phone':'15022221111'},{'jobnumber':'0011','name':'下线','role':'1','entrydate':'2015-11-11','phone':'15022221111'},{'jobnumber':'0012','name':'泡菜小锅','role':'2','entrydate':'2015-11-11','phone':'15022221111'},{'jobnumber':'0013','name':'周周','role':'1','entrydate':'2015-11-11','phone':'15022221111'},{'jobnumber':'0014','name':'下班','role':'1','entrydate':'2015-11-11','phone':'15022221111'}])

db.teachers.find()

4.写一个接口,在router.js中添加获取教师列表方法

// 访问教师管理
// 查询所有---获取教师列表
router.get("/teacher/list", (req, res) => {
    Teacher.find({}).then((data, err) => {
        if (err) {
            return res.status(500).json({ //如果err,就是错误就是数据库中没有
                code: 3000,
                flag: false,
                message: "服务器后台错误"
            })
        }
        // 分页需要数据的长度
        let content = data.length

        return res.status(200).json({
            "code": 2000,
            "flag": true,
            "message": "查询成功",
            "data": {
                content,
                "rows": data
            } //把数据返回出去
        })
    })
})

三、 Api 调用接口

1. 在 src/api 下创建 teacher.js , 调用接口代码如下: 

import request from "@/utils/request";
export function getTeacherList() { //获取教师列表
    return request({
        url: "/teacher/list", //和node接口地址一致
        method: "get",
    })
}

2. 在 src\views\teacher\index.vue 中, 添加 JS 代码如下: 

import { getTeacherList } from "@/api/teacher";

export default {
    name: "Teacher",
    created() {
        this.getList()
    },
    methods: {
        getList() {
            getTeacherList().then(res => {
                console.log(res);
            }).catch(err => {
                console.log(err);
            })
        }
    }
}
</script>

3.点击教师的时候,能拿到下图数据

四、列表模板

 1. 修改 src\views\teacher\index.vue ,编写模板代码:

<template>
    <div>
        <el-table :data="tableData" height="400" border style="width: 100%">
            <el-table-column type="index" label="序号"> </el-table-column>
            <el-table-column prop="jobnumber" label="工号"> </el-table-column>
            <el-table-column prop="name" label="姓名"> </el-table-column>
            <el-table-column prop="role" label="职务"></el-table-column>
            <el-table-column prop="entrydate" label="入职时间"> </el-table-column>
            <el-table-column prop="phone" label="电话"> </el-table-column>
        </el-table>
    </div>
</template>

<script>
import { getTeacherList } from "@/api/teacher";

export default {
    name: "Teacher",
    data() {
        return {
            tableData: []
        }
    },
    created() {
        this.getList()
    },
    methods: {
        getList() {
            getTeacherList().then(res => {
                this.tableData = res.data.data.rows
            }).catch(err => {
                console.log(err);
            })
        }
    }
}
</script>

<style></style>

五、解决CSS问题

之前的页面有些问题,下面改正:

1.去App.vue

<template>
  <div id="app" v-cloak>
    <router-view />
  </div>
</template>

<style >
body,
html {
  margin: 0 auto;
  width: 100%;
  height: 100%;
}
#app {
  width: 100%;
  height: 100%;
  overflow: hidden;
}
[v-cloak] {
  display: none;
}
</style>

2.layout.vue:

<template>
  <div class="layout">
    <app-header />
    <app-main />
    <app-navbar />
  </div>
</template>

<script>
import AppHeader from "./AppHeader/index.vue";
import AppMain from "./AppMain/index.vue";
import AppNavbar from "./AppNavbar/index.vue";
export default {
  components: {
    AppHeader,
    AppMain,
    AppNavbar,
  },
};
</script>

<style scoped>

.layout {
  width: 100%;
  height: 100%;
}
</style>

3AppHeader的index.vue:

<style scoped>
.header {
  position: absolute;
  line-height: 50px;
  background-color: cornflowerblue;
  padding: 0;
  top: 0;
  width: 100%;
}

.logo {
  vertical-align: middle;
  width: 30px;
  padding: 0 10px 0 50px;
}
.company {
  position:absolute;
  color: white;
}
a {
  text-decoration: none;
}
.el-dropdown {
  float: right;
  margin-right: 40px;
  cursor: pointer;
  color: white;
}
</style>

4.AppNavbar的index.vue:

<style scoped>
.navbar {
  position: absolute;
  top: 50px;
  width: 16%;
  left: 0;
  background-color: darkseagreen;
  overflow: hidden;
}

5.AppMain的index.vue:

<style scoped>
.main {
  position: absolute;
  top: 50px;
  left: 16%;
  width: 80%;
  padding: 10px;
  background-color: pink;
  overflow: hidden;
  /* z-index: 99; */
}

六、过滤器实现数据转换 

1. 用过滤器在teacher的index.vue中,添加一个规则,然后去组件当中去使用,由于他只需要在当前组件中使用,所以写局部的一个:

<script>
import { getTeacherList } from "@/api/teacher";
let roleOptions = [
    { type: "1", name: "班主任" },
    { type: "2", name: "教师" },
];
export default {
    name: "Teacher",
    data() {
        return {
            tableData: [],
        }
    },
    created() {
        this.getList()
    },
    methods: {
        getList() {
            getTeacherList().then(res => {
                console.log(res.data.data.rows);
                this.tableData = res.data.data.rows
            }).catch(err => {
                console.log(err);
            })
        }
    },
    filters: {
        roleFilter(val) {
            // if (val == '1') {
            //     val = '班主任'
            // } else {
            //     val = '教师'
            // }
            //   return val
            // ------------------------------------
            // obj return出来的是符合条件的那一条数据
            let obj = roleOptions.find(item => {
                return item.type === val
            })
            return obj ? obj.name : null
        }
    }
}
</script>

2.修改 模板代码

<el-table-column prop="role" label="职务">
    <template slot-scope="scope">
        <span style="margin-left: 10px">{{ scope.row.role | roleFilter }</span>
    </template>
</el-table-column>

3.在“电话”后添加删除和修改:

 <el-table-column label="操作">
        <template slot-scope="scope">
          <el-button size="mini" @click="handleEdit(scope.$index, scope.row)"
            >编辑</el-button
          >
          <el-button
            size="mini"
            type="danger"
            @click="handleDelete(scope.$index, scope.row)"
            >删除</el-button
          >
        </template>
      </el-table-column>

4.在方法里添加:

 handleEdit(index, row) {
      console.log(index, row);
    },
    handleDelete(index, row) {
      console.log(index, row);
    },

七、分页功能实现

1.为列表数据添加分页功能,使用分页组件完成分页功能,去node文件的router.js中,添加分页模拟接口

// 分页
router.post("/teacher/listPage", (req, res) => {
    console.log(req.body);
})

2. Api 调用接口,在 src\api 下的 teacher.js ,增加分页查询

export function getListPage(page, size, searchMap) { //分页
    return request({
        url: "/teacher/listPage",
        method: "post",
        data: {
            page,
            size,
            searchMap
        }
    })
}

3.在 src\views\teacher\index.vue 中,引入

import { getTeacherList, getListPage } from "@/api/teacher";

在created 时获取分页数据:

 created() {
        this.getList()
        this.ListPage()
    },
    methods: {
        // 1.获取教师列表
        getList() {
            getTeacherList().then(res => {
                console.log(res.data.data.rows);
                this.tableData = res.data.data.rows
            }).catch(err => {
                console.log(err);
            })
        },
        // 分页
        ListPage() {
            getListPage(1, 2, 3).then(res => {//先传参数,看后端是否接收到
                console.log(res);
            }).catch(err => {
                console.log(err);
            })
        },

 后台拿到数据:

  现在添加HTML分页的模板,添加代码如下:

<template>
    <div>
        <el-table :data="tableData" height="400" border style="width: 100%">
            <el-table-column type="index" label="序号"> </el-table-column>
            <el-table-column prop="jobnumber" label="工号"> </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="入职时间"> </el-table-column>
            <el-table-column prop="phone" label="电话"> </el-table-column>
            <el-table-column label="操作">
                <template slot-scope="scope">
                    <el-button size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
                    <el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)">删除</el-button>
                </template>
            </el-table-column>
        </el-table>
        <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage"
            :page-sizes="[100, 200, 300, 400]" :page-size="100" layout="total, sizes, prev, pager, next, jumper"
            :total="400">
        </el-pagination>
    </div>
</template>

现在分页效果:

 数据都是假的,我们让他展示从后台拿到的数据

4.在data里:

    data() {
        return {
            tableData: [],
            currentPage: 1,//当前页数
            pageSize: 5,//每页显示多少条数据
            pageSizes: [5, 10, 15, 20],// 每页显示个数选择器的选项设置
            total: 0,
            searchMap: {}//后面用来搜索查询的数据
        }
    },

5.在node终端能拿到页码数,然后在node的router.js中:

// 分页
router.post("/teacher/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 = {} //用来接收??数据
    Teacher.find(obj).then((data, err) => { //去数据库中查找
        if (err) {
            return res.status(500).json({
                code: 3000,
                flag: false,
                message: "服务器后台错误"
            })
        }
        let content = data.length

        //skip跳过多少条,limit查询多少个,exec当前面的代码,执行完毕后,产生的回调
        Teacher.find(obj).skip((page - 1) * parseInt(size)).limit(parseInt(size)).exec().then((data, err) => {
            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
                }
            })
        })
    })
})

6.我们获取的列表数据显示在页面上,这次是用分页接口拿到了数据列表,上面的获取教师列表接口和函数,可以不用了,用分页接口返回来的数据就可以,他刚好按分页返回来的数据,代码:

 created() {
        // this.getList()
        this.ListPage()
    },
// 1.获取教师列表
        // getList() {
        //     getTeacherList().then(res => {
        //         this.tableData = res.data.data.rows
        //     }).catch(err => {
        //         console.log(err);
        //     })
        // },
        // 分页并获取教师列表
        ListPage() {
            getListPage(this.currentPage, this.pageSize, this.searchMap).then(res => {
                // console.log(res);
                let resArr = res.data
                this.total = resArr.data.content
                this.tableData = resArr.data.rows
            }).catch(err => {
                console.log(err);
            })
        },

7.运行效果:

八、解决动态页码和当前页 

问题:上面当你改变页码后,请求URL的 {page}/{size} 不会变,一直是初始值,那是因为没有监听到改变的值。

解决:在 methods 中添加函数,

 handleSizeChange(val) {
            this.pageSize = val;
            this.ListPage()
        },
 handleCurrentChange(val) {
            this.currentPage = val;
            this.ListPage()
        },

3. 测试可通过。

九、条件查询实现-----在列表上方添加查询功能。

1. 修改 src\views\teacher\index.vue ,增加条件查询模板代码,并在方法中去调用他们:

<template>
    <div>
        <!-- 搜索区 -->
        <el-form :inline="true" :model="searchMap" ref="searchForm" class="demo-form-inline">
            <!-- 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="选择日期" 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-form-item>
        </el-form>
        <!-- 教师列表 -->
        <el-table :data="tableData" height="400" border style="width: 100%">
            <el-table-column type="index" label="序号"> </el-table-column>
            <el-table-column prop="jobnumber" label="工号"> </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="入职时间"> </el-table-column>
            <el-table-column prop="phone" label="电话"> </el-table-column>
            <el-table-column label="操作">
                <template slot-scope="scope">
                    <el-button size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
                    <el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)">删除</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="total, sizes, prev, pager, next, jumper" :total="total">
        </el-pagination>
    </div>
</template>

2.js部分:

<script>
import { getListPage } from "@/api/teacher";
let roleOptions = [
    { type: "1", name: "班主任" },
    { type: "2", name: "教师" },
];
export default {
    name: "Teacher",
    data() {
        return {
            tableData: [],//列表——教师列表数据
            currentPage: 1,//当前页数
            pageSize: 5,//每页显示多少条数据
            pageSizes: [5, 10, 15, 20],// 每页显示个数选择器的选项设置
            total: 0,
            searchMap: {//搜索栏数据
                jobnumber: "",
                name: "",
                role: "",
                entrydate: ""
            },
            roleOptions//简写形式,=>roleOptions:roleOptions
        }
    },
    created() {
        this.ListPage()// 页面初始化完成加载分页并获取教师列表
    },
    methods: {
        // 分页并获取教师列表
        ListPage() {
            getListPage(this.currentPage, this.pageSize, this.searchMap).then(res => {
                // console.log(res);
                let resArr = res.data
                this.total = resArr.data.content
                this.tableData = resArr.data.rows
            }).catch(err => {
                console.log(err);
            })
        },
        // 编辑
        handleEdit(index, row) {
            console.log(index, row);
        },
        // 删除
        handleDelete(index, row) {
            console.log(index, row);
        },
        //element-ui 的控制表格方法
        handleSizeChange(val) {
            this.pageSize = val;
            this.ListPage()
        },
        //element-ui 的控制表格方法
        handleCurrentChange(val) {
            this.currentPage = val;
            this.ListPage()
        },
        // 查询
        onSubmit() {
            // 点击查询,重新分页并获取教师列表
            this.currentPage = 1;
            this.ListPage()
        },
        //element-ui 的重置方法
        resetForm(formName) {
            this.$refs[formName].resetFields();
            // 点击重置,重新分页并获取教师列表
            this.currentPage = 1;
            this.ListPage()
        }
    },
    filters: {
        roleFilter(val) {
            // if (val == '1') {
            //     val = '班主任'
            // } else {
            //     val = '教师'
            // }
            //   return val
            // ------------------------------------
            // obj return出来的是符合条件的那一条数据
            let obj = roleOptions.find(item => {
                return item.type === val
            })
            return obj ? obj.name : null
        }
    }
}
</script>

3.在node文件的router.js中,添加条件查询代码:

// 分页
router.post("/teacher/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.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
    console.log(searchMap, obj);
    Teacher.find(obj).then((data, err) => { //去数据库中查找
        if (err) {
            return res.status(500).json({
                code: 3000,
                flag: false,
                message: "服务器后台错误"
            })
        }
        let content = data.length

        //skip跳过多少条,limit查询多少个,exec当前面的代码,执行完毕后,产生的回调
        Teacher.find(obj).skip((page - 1) * parseInt(size)).limit(parseInt(size)).exec().then((data, err) => {
            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
                }
            })
        })
    })
})

注释:searchMap和obj都是能去数据库中查到数据的,直接用searchMap也能查到数据,为什么还要再用obj去查询数据?

原因:先看图:

 如图,因为searchMap打印的是所有的条件,而obj打印的是你在搜索栏输入了哪个条件,就会根据哪个条件去查找

4.接下来我们的搜索栏部分就完成了,但是测试的时候发现时间查询查不到数据,我们看看问题出现在哪里,(学会查看问题是开发中很重要的一步):

我们在后台看到时间打印出来的信息:

 

 而我们存储数据时的格式是这样的:

我们去element-ui官网去查找看有没有控制格式的,我们发现: 

 所以我们添加value-format="yyyy-MM-dd"就好了:

<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>

后台时间格式:

查询成功:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值