0
点赞
收藏
分享

微信扫一扫

Vue项目 成员管理系统 教师管理模块(6)

小龟老师 2022-03-23 阅读 62

目录

一、教师管理-列表查询

1.1 nodejs 添加数据列表接口

1.1.1 创建teacher.js

1.1.2 router.js中添加获取教师列表方法

1.2 Api调用接口 

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

1.2.2在数据库中手动添加数据,以供测试:

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

1.3 列表模板

1.3.1修改 src\views\teacher\index.vue 

1.4 过滤器实现数据转换 

1.4.1通过 filters 选项来定义过滤器来实现转换

 1.4.2 修改 模板代码

1.5 分页功能实现 

 1.5.1 分页模板

1.5.2  Api 调用接口

1.5.3 nodejs添加会员分页模拟接口

 1.6  条件查询实现

1.6.1 修改 src\views\teacher\index.vue ,增加条件查询模板代码

1.6.2 在 data 选项声明 roleOptions属性用于下拉框 ,并将全局的赋值给它

1.6.3 methods中添加searchData方法

二、教师管理-新增 

2.1 新增窗口实现

2.1.1 在 src\views\teacher\index.vue 中分页区域的下方,新增对话框形式表单数据模板

2.1.2 在 methods 中添加 handleAdd() 函数

2.2 表单数据校验

2.2.1 在新增窗口的 el-form 上绑定属性 :rules="rules"

2.3 表单数据提交

2.3.1 nodejs 添加新增教师接口

2.3.2 Api调用接口 

三、 教师管理-修改

3.1 nodejs添加接口

3.1.1 ID 查询数据接口

3.1.2 提交修改数据接口

3.2 Api调用接口

3.2.1 src\api\teacher.js 导出的默认对象中,添加ID查询方法 getById和更新方法 update

3.2.2 在 src\views\teacher\index.vue 中的 handleEdit 方法做如下修改:

3.2.3 修改对话框中的确认按钮点击事件  

3.2.4 提交更新数据

四、教师管理-删除 

4.1 nodejs添加接口

4.1.1 教师删除接口

4.2 Api调用接口 

4.2.1 src\api\teacher.js 导出的默认对象中,添加 deleteById 方法

4.2.2 在 src\views\teacher\index.vue 中的 handleDele 方法做如下修改:



一、教师管理-列表查询

1.1 nodejs 添加数据列表接口

1.1.1 创建teacher.js

node.js配置

//!读写数据库
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/stu');

//?定义规则对象
var Schema = mongoose.Schema;//声明mongoose下的一个规则
var userSchema = new Schema({//创建一个规则的对象,生成一个这样规则的实例
    jobnumber: {//工号
        type: String,
        require: true
    },
    name: {
        type: String,
        require: true
    },
    role: {//职位
        type: String,
        require: true
    },
    entrydate: {//入职时间
        type: String,
        require: true
    },
    phone: {
        type: String,
        require: true
    }
})
module.exports = mongoose.model('Teacher', userSchema);//默认去找表名为teachers

1.1.2 router.js中添加获取教师列表方法

在router.js中导入teacher.js

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

添加获取教师列表方法

router.get('/teacher/list', function (req, res) {
    Teacher.find({}, function (err, data) {//因为要查询所有,所以条件可以不用写
        if (err) {
            res.status(500).json({
                code: 4000,
                flag: false,
                message: 'server error'
            })
        }
        return res.status(200).json({
            code: 2000,
            flag: true,
            message: '查找教师信息成功',
            data: {
                total: data.length,//后面涉及到分页问题,需要获取数组长度
                rows: data,
            }
        })
    })
})

1.2 Api调用接口 

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

import request from '@/utils/request.js'

export default {
    getList() {
        return request({
            url: '/teacher/list',
            method: 'get',
        })
    }
}

1.2.2在数据库中手动添加数据,以供测试:

成功查询:

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

<script>
import teacherApi from '@/api/teacher.js'
//因为在teacher.js中默认导出对象,所以接受的时候就不能用大括号的形式去接收
export default {
    data() {
        return {
            tableData: [],//调用的element-ui中的table的data为tableData
            total: 0
        }
    },

    components: {},
    created() {
        this.fetchData();//在钩子函数中调用下面写的方法
    },
    methods: {
        fetchData() {
            teacherApi.getList().then(response => {
                const resp = response.data;
                // console.log(resp);
                this.tableData = resp.data.rows;
                this.total = resp.data.total;
            })
        }
    },

}
</script>

1.3 列表模板

1.3.1修改 src\views\teacher\index.vue 

编写模板代码:表格采用的是固定表头

参考: Element - The world's most popular Vue UI framework

<template>
    <div class="table">
        <el-table
            :data="tableData"
            height="250"
            border
            style="width: 100%"
        >
            <el-table-column
                type="index"
                label="序号"
                width="80"
            >
                <!-- 用index绑定序号的时候,前边不能用prop,而需要用type -->
            </el-table-column>
            <el-table-column
                prop="jobnumber"
                label="工号"
                width="180"
            >
            </el-table-column>
            <el-table-column
                prop="name"
                label="姓名"
                width="180"
            >
            </el-table-column>
            </el-table-column>
            <el-table-column
                prop="role"
                label="职位"
                width="180"
            >
            </el-table-column>
            </el-table-column>
            <el-table-column
                prop="entrydate"
                label="入职时间"
                width="180"
            >
            </el-table-column>
            <el-table-column
                prop="phone"
                label="联系方式"
            >
            </el-table-column>
            <el-table-column label="操作">
                <!--
                    在Element-ui中,要在某一个元素中放一个按钮的话,
                    需要在按钮外面套一层template标签,因为element框架封装时的要求.
                -->
                <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>

1.4 过滤器实现数据转换 

1.4.1通过 filters 选项来定义过滤器来实现转换

渲染后发现职务类型是编号,应该将类型编号 转为名称.

JS 脚本处声明一个全局职务类型数组, 组件对象的 filters 选项指定转换规则.

const roleOptions = [//全局定义职位类型的数组
    {
        type: '1', name: '班主任'
    },
    {
        type: '2', name: '数学老师'
    },
    {
        type: '3', name: '语文老师'
    },
    {
        type: '4', name: '英语老师'
    }
];
filters: {//过滤器
        roleFilter(type) {
            const obj = roleOptions.find(item => item.type === type)
            //箭头函数后边是查询条件 find方法中是function
            /* 表示数组中某一项的type如果与传进来的type一致,就把这项返回 */
            return obj ? obj.name : null;//三元表达式,如果没有obj就返回空值
        }
    },

 1.4.2 修改 模板代码

            <el-table-column
                prop="role"
                label="职位"
                width="180"
            >
                <template slot-scope="scope">
                    <span>{{scope.row.role | roleFilter}}</span>
                </template>
            </el-table-column>

1.5 分页功能实现 

为列表数据添加分页功能,使用分页组件完成分页功能。

参考:Element - The world's most popular Vue UI framework

添加数据,以达到分页显示的目的:

 1.5.1 分页模板

修改 src\views\teacher\index.vue , template 标签中添加页面模板代码:

        <!-- 分页功能 -->
        <el-pagination
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="this.currentPage"
            :page-sizes="[5, 10, 20]"
            :page-size="this.pageSize"
            layout="total, sizes, prev, pager, next, jumper"
            :total="this.total"
        >
        </el-pagination>

注意:添加在 div 里面,因为 template 里面只能有唯一根节点.

返回数据以及方法:

data() {
        return {
            tableData: [],
            total: 0,
            currentPage: 1,
            pageSize: 10,
            seachMap: {//所有教师的所有项
                jobnumber: '',
                name: '',
                role: '',
                entrydate: ''
            }
        }
    },
    filters: {//过滤器
        roleFilter(type) {
            const obj = roleOptions.find(item => item.type === type)//箭头函数后边是查询条件 find方法中是function
            /* 表示数组中某一项的type如果与传进来的type一致,就把这项返回 */
            return obj ? obj.name : null;//三元表达式,如果没有obj就返回空值
        }
    },
    components: {},
    created() {
        this.fetchData();//在钩子函数中调用下面写的方法
    },
    methods: {
        fetchData() {
            teacherApi.search(this.currentPage, this.pageSize, this.seachMap).then(response => {
                const resp = response.data;
                // console.log(resp);
                this.tableData = resp.data.rows;
                this.total = resp.data.total;//记录读取多少条
            })
        },
        handleSizeChange(val) {
            console.log(`每页 ${val} 条`);
            this.pageSize = val;
            this.fetchData();
        },
        handleCurrentChange(val) {
            console.log(`当前页: ${val}`);
            this.currentPage = val;
            this.fetchData();
        }
    }

1.5.2  Api 调用接口

修改 src\api 下的 teacher.js , 在导出的默认对象中,增加分页查询方法

search(page, size, searchMap) {//通过axios请求将这三个参数传到服务端
        return request({
            url: '/teacher/search',
            method: 'post',
            data: {
                page,//page 当前要查询的页码
                size,//size 每页显示条数
                searchMap//所有教师的所有项
            }
        })
    }

修改fetchData方法:

fetchData() {
            teacherApi.search(this.currentPage, this.pageSize, this.seachMap)
            .then(response => {
                const resp = response.data;
                // console.log(resp);
                this.tableData = resp.data.rows;
                this.total = resp.data.total;//记录读取多少条
            })
        },

1.5.3 nodejs添加会员分页模拟接口

router.js中添加方法:

//?修改教师信息(分页)
router.post('/teacher/list', function (req, res) {
    const body = req.body;
    //* 前端传入
    let page = body.page || 1;//如果传的时候没有值,默认值就为1.
    let size = body.size || 10;
    let searchMap = body.searchMap || {};
    //* 后端真正查询条件
    const obj = {};
    searchMap.jobnumber ? obj["jobnumber"] = searchMap.jobnumber : obj;
    //判断searchMap中是否有jobnumber这一项,如果存在就在obj中添加一项jobnumber等于searchMap.jobnumber,没有就为空.
    searchMap.name ? obj["name"] = searchMap.name : obj;
    searchMap.role ? obj["role"] = searchMap.role : obj;
    searchMap.entrydate ? obj["entrydate"] = searchMap.entrydate : obj;
    Teacher.find(obj, function (err, data) {//obj有内容就按照obj的内容去查询,没有内容就相当于空对象
        //todo find方法无论有没有条件,返回的都是数组.
        if (err) {
            return res.status(500).json({
                code: 3000,
                flag: false,
                message: 'server error'
            })
        }
        let count = data.length;//查询到数据后,记录data中有多少数据.
        //*进行分页查询
        Teacher.find(obj).skip((page - 1) * parseInt(size)).limit(parseInt(size)).exec(function (err, data) {
            //skip 跳过 limit 截取.
            //通过find查找, 拿到数据后进行skip,limit.这种写法无法写回调函数,通过exec方法来拿到返回值
            if (err) {
                res.status(500).json({
                    code: 3000,
                    flag: false,
                    message: 'server error'
                })
            }
            return res.status(200).json({
                code: 2000,
                flag: true,
                message: '成功查询! 查询信息如下',
                data: {
                    total: count,
                    rows: data
                }
            })
        })
    })
})

成功分页查询:

 1.6  条件查询实现

在列表上方添加查询条件

1.6.1 修改 src\views\teacher\index.vue ,增加条件查询模板代码

<!-- 条件查询 -->
        <el-form
            :inline="true"
            :model="searchMap"
            ref="searchForm"
            class="demo-form-inline"
        >
            <el-form-item prop="jobnumber">
                <el-input
                    v-model="searchMap.jobnumber"
                    placeholder="工号"
                ></el-input>
            </el-form-item>
            <el-form-item prop="name">
                <el-input
                    v-model="searchMap.name"
                    placeholder="姓名"
                ></el-input>
            </el-form-item>
            <el-form-item prop="role">
                <el-select
                    v-model="searchMap.role"
                    placeholder="教师职务"
                >
                    <!-- 循环 绑定相应数据 -->
                    <el-option
                        v-for="option in roleOptions"
                        :key="option.type"
                        :label="option.name"
                        :value="option.type"
                    ></el-option>
                </el-select>
            </el-form-item>
            <el-form-item prop="entrydate">
                <span class="demonstration"></span>
                <!-- 使用 value-format 保证格式与数据库中一致 -->
                <el-date-picker
                    value-format="yyyy-MM-dd"
                    v-model="searchMap.entrydate"
                    type="date"
                    placeholder="入职时间"
                >
                </el-date-picker>
            </el-form-item>
            <el-form-item>
                <el-button
                    type="primary"
                    @click="searchData"
                >查询</el-button>
                <el-button type="primary">新增</el-button>
                <el-button
                    type="primary"
                    @click="resetForm"
                >重置</el-button>
            </el-form-item>
        </el-form>

条件查询表单中需要在每一个el-form-item标签中添加prop属性,绑定相应的key值,不然获取不到数据.

1.6.2 在 data 选项声明 roleOptions属性用于下拉框 ,并将全局的赋值给它

v-model绑定必须是相应实例里的数据.

data() {
        return {
            tableData: [],
            total: 0,
            currentPage: 1,
            pageSize: 10,
            searchMap: {//所有教师的所有项
                jobnumber: '',
                name: '',
                role: '',
                entrydate: ''
            },
            roleOptions//ES6
        }
    },

1.6.3 methods中添加searchData方法

        searchData() {
            this.currentPage = 1;//将页码设置回1,防止后台只查询到1条数据,但是却返回其他页码,从而数据返回空
            this.fetchData();
        },
        resetForm(formName) {
            this.$refs[formName].resetFields();
        },

测试,成功查询:


二、教师管理-新增 

2.1 新增窗口实现

2.1.1 在 src\views\teacher\index.vue 中分页区域的下方,新增对话框形式表单数据模板

el-dialog 标答属性 title 窗口标题,visible.sync 是否弹出窗口

<!-- 新增教师弹窗 -->
        <el-dialog
            title="教师信息编辑"
            :visible.sync="dialogFormVisible"
            width='500px'
        ><!-- :visible.sync 控制弹窗 -->
            <el-form
                :model="teacher"
                ref="teacherForm"
                label-width='100px'
                label-position='right'
                style="width:400px"
            >
                <el-form-item
                    label="工号"
                    prop='jobnumber'
                >
                    <el-input
                        v-model="teacher.jobnumber"
                        autocomplete="off"
                    ></el-input>
                </el-form-item>
                <el-form-item
                    label="姓名"
                    prop='name'
                >
                    <el-input
                        v-model="teacher.name"
                        autocomplete="off"
                    ></el-input>
                </el-form-item>
                <el-form-item
                    label="职务"
                    prop='role'
                >
                    <el-select
                        v-model="teacher.role"
                        placeholder="请选择..."
                    >
                        <el-option
                            v-for="option in roleOptions"
                            :key="option.type"
                            :label="option.name"
                            :value="option.type"
                        ></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item
                    prop="entrydate"
                    label='入职时间'
                >
                    <span class="demonstration"></span>
                    <!-- 使用 value-format 保证格式与数据库中一致 -->
                    <el-date-picker
                        value-format="yyyy-MM-dd"
                        v-model="teacher.entrydate"
                        type="date"
                        placeholder="入职时间"
                    >
                    </el-date-picker>
                </el-form-item>
                <el-form-item
                    label="电话"
                    prop='phone'
                >
                    <el-input
                        v-model="teacher.phone"
                        autocomplete="off"
                    ></el-input>
                </el-form-item>
            </el-form>
            <div
                slot="footer"
                class="dialog-footer"
            >
                <el-button @click="dialogFormVisible = false">取 消</el-button>
                <el-button type="primary">确 定</el-button>
            </div>
        </el-dialog>
    </div>

弹窗实现:

2.1.2 在 methods 中添加 handleAdd() 函数

打开新增对话框关闭窗口后,再次打开窗口,会发现表单里依然有数据,应当清除数据。  

handleAdd() {
            this.dialogFormVisible = true;
            // this.$refs['teacherForm'].resetFields();
            /* 直接调用方法的时候,DOM层渲染的窗口没加载出来,表单也就没有生成,
            但是this.$的方法是异步加载的,表单未加载出来的时候重置功能就开始执行,找不到表单实例,所以控制台会报错 */
            this.$nextTick(() => {
                this.$refs['teacherForm'].resetFields();
            })
            /* this.$nextTick()它是一个异步事件,当渲染结束之后 ,它的回调函数才会被执行
            弹出窗口打开之后 ,需要加载Dom, 就需要花费一点时间,等待它加载完dom之后,再进行调用resetFields方法,重置表单和清除样式*/
        },

2.2 表单数据校验

2.2.1 在新增窗口的 el-form 上绑定属性 :rules="rules"

            <el-form
                :model="teacher"
                ref="teacherForm"
                label-width='100px'
                label-position='right'
                style="width:400px"
                :rules='rules'
            >

2.2.2 在 data 选项中添加 rules 属性进行校验,对工号,姓名 校验  

    rules:{
                jobnumber: [{ required: true, message: '请输入工号', trigger: 'blur' }],
                name: [{ required: true, message: '请输入姓名', trigger: 'blur' }]
            },

 

2.3 表单数据提交

2.3.1 nodejs 添加新增教师接口

router.js中新增方法

//?新增教师
router.post('/teacher/add', function (req, res) {
    var body = req.body;
    new Teacher(body).save(function (err) {//往mongo中添加数据 使用 new Teacher().save
        if (err) {//只需要判断是否存在,不需要将存的数据再返回来一遍
            return res.status(500).json({
                code: 3000,
                flag: false,
                message: 'server error'
            })
        }
        return res.status(200).json({
            code: 2000,
            flag: true,
            message: '成功添加'
        })
    })
})

2.3.2 Api调用接口 

src\api\teacher.js 导出的默认对象中,添加调用新增接口的方法

add(teacher) {
        return request({
            url: '/teacher/add',
            method: 'post',
            data: teacher
        })
    }

 在 src\views\teacher\index.vue 中的 addData 方法中提交数据,代码如下:

addData(formName) {
            this.$refs[formName].validate((valid) => {
                if (valid) {
                    //向数据库中添加数据,成功后重新查询刷新列表
                    // alert('submit!');
                    teacherApi.add(this.teacher).then(response => {
                        const resp = response.data;
                        if (resp.flag) {
                            this.fetchData();//新增成功,刷新列表数据
                            this.dialogFormVisible = false;//添加完成后,自动关闭弹窗
                            this.$message({
                                message: '添加教师信息成功',
                                type: 'success'
                            })
                        } else {
                            this.$message({
                                message: resp.message,
                                type: 'warning'
                            })
                        }
                    })
                } else {
                    //返回添加失败提示
                    console.log('error submit!!');
                    return false;
                }
            });
        },

添加教师信息成功: 

 


三、 教师管理-修改

3.1 nodejs添加接口

3.1.1 ID 查询数据接口

//?根据id查找一条教师信息
router.get('/teacher', function (req, res) {
    Teacher.findById(req.query.id, function (err, data) {
        if (err) {
            return res.status(500).json({
                code: 3000,
                flag: false,
                message: 'server error'
            })
        }
        return res.status(200).json({
            code: 2000,
            flag: true,
            message: '根据id查找教师信息成功',
            data: data
        })
    })
})

3.1.2 提交修改数据接口

//?根据id修改一条教师信息(put方法,在使用上与post方法一样)
router.put('/teacher', function (req, res) {
    var id = req.body._id;//与前端传过来的key值要对应
    Teacher.findByIdAndUpdate(id, req.body, function (err) {//findByIdAndUpdate方法参数分别为,id,整个对象,方法
        if (err) {
            return res.status(500).json({
                code: 3000,
                flag: false,
                message: 'server error'
            })
        }
        return res.status(200).json({
            code: 2000,
            flag: true,
            message: '修改教师信息成功'
        })
    })
})

3.2 Api调用接口

3.2.1 src\api\teacher.js 导出的默认对象中,添加ID查询方法 getById和更新方法 update

getById(id) {
        return request({
            url: `/teacher?id=${id}`,
            method: 'get'
        })
    },
    update(teacher) {
        return request({
            url: '/teacher',
            method: 'put',
            data:teacher
        })
    }

3.2.2 在 src\views\teacher\index.vue 中的 handleEdit 方法做如下修改:

handleEdit(id) {
            // console.log('edit', id);
            this.handleAdd();
            teacherApi.getById(id).then(response => {
                const resp = response.data;
                if (resp.flag) {
                    this.teacher = resp.data;
                }
            })
        },

3.2.3 修改对话框中的确认按钮点击事件  

            <el-button
                    type="primary"
                    @click=" teacher._id === null ? addData('teacherForm') :     
            updateData('teacherForm')"
                >确 定</el-button><!-- 通过判断id是否为空来进行新增功能或者编辑功能 -->

3.2.4 提交更新数据

updateData(formName) {
            this.$refs[formName].validate((valid) => {
                if (valid) {
                    teacherApi.update(this.teacher).then(response => {
                        const resp = response.data;
                        if (resp.flag) {
                            this.fetchData();//刷新列表数据
                            this.dialogFormVisible = false;//关闭窗口
                            this.$message({
                                message: resp.message,
                                type: 'success'
                            })
                        } else {
                            this.$message({
                                message: resp.message,
                                type: 'warning'
                            })
                        }
                    })
                } else {
                    return false;
                }
            })
        },

修改成功: 


四、教师管理-删除 

4.1 nodejs添加接口

4.1.1 教师删除接口

//?根据id删除一条教师信息(delete方法)
router.delete('/teacher', function (req, res) {
    // console.log(req.body);
    Teacher.findByIdAndRemove(req.body.id, function (err) {
        if (err) {
            return res.status(500).json({
                code: 3000,
                flag: false,
                message: 'server error'
            })
        }
        return res.status(200).json({
            code: 2000,
            flag: true,
            message: '删除教师信息成功'
        })
    })
})

4.2 Api调用接口 

4.2.1 src\api\teacher.js 导出的默认对象中,添加 deleteById 方法

deleteById(id) {
        return request({
            url: `/teacher`,
            method: 'delete',
            data: { id }
        })
    }

4.2.2 在 src\views\teacher\index.vue 中的 handleDele 方法做如下修改:

handleDelete(id) {
            // console.log('delete', id);
            this.$confirm('确认删除这条数据吗?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {//点击`确定`
                teacherApi.deleteById(id).then(response => {
                    this.$message({
                        type: response.data.flag ? 'success' : 'error',
                        message: response.data.message
                    });
                    if (response.data.flag) {
                        this.fetchData();//将数据库中新的数据再获取一遍
                    }
                })
            }).catch(() => {//点击`取消`
                this.$message({
                    message: '已取消删除',
                    type: 'info'
                })
            });
        },

 成功删除:


举报

相关推荐

0 条评论