VUE3.0+Antdv+Asp.net WebApi开发学生信息管理系统(三)

简介: VUE3.0+Antdv+Asp.net WebApi开发学生信息管理系统(三)

在B/S系统开发中,前后端分离开发设计已成为一种标准,而VUE作为前端三大主流框架之一,越来越受到大家的青睐,Antdv是Antd在Vue中的实现。本系列文章主要通过Antdv和Asp.net WebApi开发学生信息管理系统,简述前后端分离开发的主要相关内容,仅供学习分享使用,如有不足之处,还请指正。

在本示例项目中,主要包含两大部分:1.前端web项目【vsims.web】2.后端webapi项目【vsims.webapi】,经过前两篇文章的讲解,已经对前端项目的架构和组成部分,以及后端webapi项目的开发有了大致了解。今天继续开发学生管理模块,主要讲解列表,表单开发的相关内容。

涉及知识点


在本示例中,涉及知识点,主要是前端开发相关:

  • 开发工具:HbuilderX
  • 项目框架:VUE3.0+Antdv
  • Antdv控件应用:
  • 列表(a-table):主要用于大量结构化数据的呈现。
  • 表单(a-form):主要用于收集信息,然后提交到后台进行处理,以及数据进行校验等操作。
  • 分页组件(a-pagination):采用分页形式分隔长列表,每次只显示一页列表。
  • 弹出对话窗(a-modal):需要用户处理事务,又不希望跳转页面以致打断工作流程时,可以使用 Modal 在当前页面正中打开一个浮层,承载相应的操作。
  • 其他控件:文本框(a-input),按钮(a-button),单选按钮(a-radio),下拉框(a-select)等控件。关于具体每一个控件的使用,可参考官网说明示例。

功能划分


在本示例中,学生管理模块功能主要分为4个部分:

  • 查询功能:根据输入的查询条件进行查询,此功能是一个form表单。
  • 数据展示:将查询出的结果进行展示,此功能是一个table列表。
  • 分页功能:数据数据较多,需要分页展示,每次展示一页数据。
  • 新增,编辑功能:可以添加学生信息,也可以编辑信息,此功能是一个弹出对话框,嵌套一个form表单。

查询功能


在学生管理模块中,查询功能主要通过学号,姓名两个条件进行查询,代码如下所示:

<a-form :model="formState" name="horizontal_query" layout="inline" autocomplete="off" @finish="onFinish" @finishFailed="onFinishFailed">
    <a-form-item label="学号" name="no">
        <a-input v-model:value="formState.no"></a-input>
    </a-form-item>
    <a-form-item label="姓名" name="name">
        <a-input v-model:value="formState.name"></a-input>
    </a-form-item>
    <a-form-item>
        <a-button type="primary" html-type="submit">查询</a-button>
    </a-form-item>
    <a-form-item>
        <a-button type="primary" @click="addStudent">新增</a-button>
    </a-form-item>
</a-form>

注意:form表单的提交事件为submit,finish为提交成功后的响应事件,在此事件中可以进行接口调用,如下所示:

const onFinish = (values: any) => {
    var no = values.no;
    var name = values.name;
    getStudents(no, name);
    console.log('Success:', values);
};
const onFinishFailed = (errorInfo: any) => {
    console.log('Failed:', errorInfo);
};
const getStudents = (no, name) => {
    dataSource.length = 0;
    getD('/api/Student/GetStudents', {
        "pageSize": pagination.pageSize,
        "pageNum": pagination.current,
        "no": no,
        "name": name
    }).then(res => {
        console.log(res);
        if (res.status == 200) {
            pagination.total = res.data.count; //总记录数
            console.log(pagination.total);
            for (let i = 0; i < res.data.items.length; i++) {
                dataSource.push({
                    id: res.data.items[i].id,
                    key: res.data.items[i].id.toString(),
                    no: res.data.items[i].no,
                    name: res.data.items[i].name,
                    age: res.data.items[i].age,
                    sex: res.data.items[i].sex ? "男" : "女",
                    sexValue: res.data.items[i].sex,
                    classesId: res.data.items[i].classesId,
                    classesName: res.data.items[i].classesName,
                });
            }
            state.dataSource = [...dataSource];
        }
    });
};

其中getStudents方法,多个地方会进行调用,所以进行了封装,主要用于学生列表查询接口访问。

数据展示


数据展示主要使用a-table控件,其中columns定义需要显示的列,data-source绑定数据源,如下所示:

<a-table :columns="columns" :data-source="dataSource" bordered :pagination="false" :row-key="record => record.id">
    <template #bodyCell="{ column, text, record }">
        <template v-if="[ 'no','name', 'sge', 'dex','classesName'].includes(column.dataIndex)">
            <div>{{ text }}</div>
        </template>
        <template v-else-if="column.dataIndex === 'operation'">
            <div class="editable-row-operations">
                <a @click="edit(record.key)">Edit</a>
            </div>
        </template>
    </template>
</a-table>

注意:默认情况下,当数据源发生更新时,a-table控件不会信息页面刷新,需要绑定row-key属性才可以。

分页功能


分页功能主要才用分页控件a-pagination,其中current表示当前页,total表示总页码,change表示绑定分页事件,如下所示:

<a-pagination v-model:current="pagination.current" :total="pagination.total" @change="change" />

关于change事件功能,主要用于调用getStudents函数,如下所示:

const change = (pagination) => {
    var no = formState.no;
    var name = formState.name;
    getStudents(no, name);
    console.log(pagination);
};

新增编辑功能


新增学生和编辑学生都是对单个学生实体进行操作,采用form表单进行提交到后台接口。其中visible用于控制弹窗的显示与隐藏。ok表示弹窗的确定事件。班级下拉框(a-select)显示班级列表,需要在加载页面时进行预加载。如下所示:

<a-modal ref="modalRef" v-model:visible="visible" okText="保存" cancelText="取消" :wrap-style="{ overflow: 'hidden' }" @ok="handleOk">
    <div>
        <a-page-header style="border: 1px solid rgb(235, 237, 240)" title="学生管理" sub-title="新增或编辑学生" />
        <a-form :model="addEditFormState">
            <a-form-item label="学号">
                <a-input v-model:value="addEditFormState.no" />
            </a-form-item>
            <a-form-item label="姓名">
                <a-input v-model:value="addEditFormState.name" />
            </a-form-item>
            <a-form-item label="年龄">
                <a-input v-model:value="addEditFormState.age" />
            </a-form-item>
            <a-form-item label="性别">
                <a-radio-group v-model:value="addEditFormState.sex">
                    <a-radio :value="true">男</a-radio>
                    <a-radio :value="false">女</a-radio>
                </a-radio-group>
            </a-form-item>
            <a-form-item label="班级">
                <a-select ref="select" v-model:value="addEditFormState.classes" style="width: 200px">
                    <a-select-option :value="item.id" v-for="(item) in dataClasses" :key="item.id">{{item.name}}</a-select-option>
                </a-select>
            </a-form-item>
        </a-form>
    </div>
</a-modal>

新增编辑提交事件handleOk代码,其中根据id值判断是新增学生和编辑学生,如下所示:

const handleOk = (e: MouseEvent) => {
    console.log(e);
    console.log(addEditFormState);
    var url = "";
    if (addEditFormState.id >0) {
        url = "/api/Student/UpdateStudent"; //编辑
    } else {
        url = "/api/Student/AddStudent"; //新增
    }
    postD(url, {
        "id": addEditFormState.id>0?addEditFormState.id:null,
        "no": addEditFormState.no,
        "name": addEditFormState.name,
        "age": addEditFormState.age,
        "sex": addEditFormState.sex,
        "classesId": addEditFormState.classes,
        "createTime": "2022-08-15T15:31:12.224Z",
        "createUser": 0,
        "lastEditTime": "2022-08-15T15:31:12.224Z",
        "lastEditUser": 0
    }).then(res => {
        console.log(res);
        if(res.status==200){
            if(res.data==0){
                message.success('保存成功!');
                visible.value = false;
                var no = formState.no;
                var name = formState.name;
                getStudents(no, name);
            }else{
                message.error('保存失败!');
            }
        }
    });
};

关于学生管理模块的全部代码,如下所示:

<template>
    <a-page-header style="border: 1px solid rgb(235, 237, 240)" title="学生管理" sub-title="学生信息基本操作" />
    <a-form :model="formState" name="horizontal_query" layout="inline" autocomplete="off" @finish="onFinish" @finishFailed="onFinishFailed">
        <a-form-item label="学号" name="no">
            <a-input v-model:value="formState.no"></a-input>
        </a-form-item>
        <a-form-item label="姓名" name="name">
            <a-input v-model:value="formState.name"></a-input>
        </a-form-item>
        <a-form-item>
            <a-button type="primary" html-type="submit">查询</a-button>
        </a-form-item>
        <a-form-item>
            <a-button type="primary" @click="addStudent">新增</a-button>
        </a-form-item>
    </a-form>
    <a-table :columns="columns" :data-source="dataSource" bordered :pagination="false" :row-key="record => record.id">
        <template #bodyCell="{ column, text, record }">
            <template v-if="[ 'no','name', 'sge', 'dex','classesName'].includes(column.dataIndex)">
                <div>{{ text }}</div>
            </template>
            <template v-else-if="column.dataIndex === 'operation'">
                <div class="editable-row-operations">
                    <a @click="edit(record.key)">Edit</a>
                </div>
            </template>
        </template>
    </a-table>
    <a-pagination v-model:current="pagination.current" :total="pagination.total" @change="change" />
    <a-modal ref="modalRef" v-model:visible="visible" okText="保存" cancelText="取消" :wrap-style="{ overflow: 'hidden' }" @ok="handleOk">
        <div>
            <a-page-header style="border: 1px solid rgb(235, 237, 240)" title="学生管理" sub-title="新增或编辑学生" />
            <a-form :model="addEditFormState">
                <a-form-item label="学号">
                    <a-input v-model:value="addEditFormState.no" />
                </a-form-item>
                <a-form-item label="姓名">
                    <a-input v-model:value="addEditFormState.name" />
                </a-form-item>
                <a-form-item label="年龄">
                    <a-input v-model:value="addEditFormState.age" />
                </a-form-item>
                <a-form-item label="性别">
                    <a-radio-group v-model:value="addEditFormState.sex">
                        <a-radio :value="true">男</a-radio>
                        <a-radio :value="false">女</a-radio>
                    </a-radio-group>
                </a-form-item>
                <a-form-item label="班级">
                    <a-select ref="select" v-model:value="addEditFormState.classes" style="width: 200px">
                        <a-select-option :value="item.id" v-for="(item) in dataClasses" :key="item.id">{{item.name}}</a-select-option>
                    </a-select>
                </a-form-item>
            </a-form>
        </div>
    </a-modal>
</template>
<script lang="ts">
    import {
        defineComponent,
        reactive,
        toRefs,
        ref,
        toRaw
    } from 'vue';
    import type {
        UnwrapRef
    } from 'vue';
    import { message } from 'ant-design-vue';
    import {
        getD,
        postD
    } from '../api/index.js';
    const columns = [
        {
            title: '学号',
            dataIndex: 'no',
            key: 'no',
            align: 'center',
            width: '20%',
        },
        {
            title: '姓名',
            dataIndex: 'name',
            key: 'name',
            align: 'center',
            width: '20%',
        },
        {
            title: '年龄',
            dataIndex: 'age',
            key: 'age',
            align: 'center',
            width: '15%',
        },
        {
            title: '性别',
            dataIndex: 'sex',
            key: 'sex',
            align: 'center',
            width: '10%',
        },
        {
            title: '班级',
            dataIndex: 'classesName',
            key: 'classesName',
            align: 'center',
            width: '20%',
        },
        {
            title: '操作',
            dataIndex: 'operation',
            key: 'operation',
            align: 'center',
        },
    ];
    interface DataItem {
        id: number,
            key: string,
            no: string,
            name: string,
            age: number,
            sex: string,
            sexValue: boolean,
            classesId: string,
            classesName: string
    }
    interface FormState {
        no: string;
        name: string;
    }
    interface ClassesItem {
        id: number,
            name: string
    }
    const pagination = {
        total: 1,
        current: 1,
        pageSize: 10,
    };
    const dataClasses: ClassesItem[] = []; //班级列表
    const dataSource: DataItem[] = [];
    export default defineComponent({
        setup() {
            const formState = reactive < FormState > ({
                no: '',
                name: '',
            });
            const addEditFormState = reactive({
                id: 0,
                no: '',
                name: '',
                age: 0,
                sex: false,
                classes: '',
            });
            const visible = ref < boolean > (false);
            const addStudent = () => {
                addEditFormState.id = -1;
                addEditFormState.no = '';
                addEditFormState.name = '';
                addEditFormState.age = 0;
                addEditFormState.classes = '';
                visible.value = true;
            };
            const handleOk = (e: MouseEvent) => {
                console.log(e);
                console.log(addEditFormState);
                var url = "";
                if (addEditFormState.id >0) {
                    url = "/api/Student/UpdateStudent"; //编辑
                } else {
                    url = "/api/Student/AddStudent"; //新增
                }
                postD(url, {
                    "id": addEditFormState.id>0?addEditFormState.id:null,
                    "no": addEditFormState.no,
                    "name": addEditFormState.name,
                    "age": addEditFormState.age,
                    "sex": addEditFormState.sex,
                    "classesId": addEditFormState.classes,
                    "createTime": "2022-08-15T15:31:12.224Z",
                    "createUser": 0,
                    "lastEditTime": "2022-08-15T15:31:12.224Z",
                    "lastEditUser": 0
                }).then(res => {
                    console.log(res);
                    if(res.status==200){
                        if(res.data==0){
                            message.success('保存成功!');
                            visible.value = false;
                            var no = formState.no;
                            var name = formState.name;
                            getStudents(no, name);
                        }else{
                            message.error('保存失败!');
                        }
                    }
                });
            };
            const onFinish = (values: any) => {
                var no = values.no;
                var name = values.name;
                getStudents(no, name);
                console.log('Success:', values);
            };
            const onFinishFailed = (errorInfo: any) => {
                console.log('Failed:', errorInfo);
            };
            const state = reactive({
                dataSource: dataSource,
                dataClasses: dataClasses
            });
            const getClasses=()=>{
                getD('/api/Classes/GetClassess', {
                    "dept": "",
                    "grade": "",
                    "pageSize": 0,
                    "pageNum": 0
                }).then(res => {
                    console.log(res);
                    if (res.status == 200) {
                        for (let i = 0; i < res.data.items.length; i++) {
                            dataClasses.push({
                                id: res.data.items[i].id,
                                name: res.data.items[i].dept +res.data.items[i].grade+ res.data.items[i].name,
                            });
                        }
                        state.dataClasses = [...dataClasses];
                    }
                });
            };
            getClasses();
            const getStudents = (no, name) => {
                dataSource.length = 0;
                getD('/api/Student/GetStudents', {
                    "pageSize": pagination.pageSize,
                    "pageNum": pagination.current,
                    "no": no,
                    "name": name
                }).then(res => {
                    console.log(res);
                    if (res.status == 200) {
                        pagination.total = res.data.count; //总记录数
                        console.log(pagination.total);
                        for (let i = 0; i < res.data.items.length; i++) {
                            dataSource.push({
                                id: res.data.items[i].id,
                                key: res.data.items[i].id.toString(),
                                no: res.data.items[i].no,
                                name: res.data.items[i].name,
                                age: res.data.items[i].age,
                                sex: res.data.items[i].sex ? "男" : "女",
                                sexValue: res.data.items[i].sex,
                                classesId: res.data.items[i].classesId,
                                classesName: res.data.items[i].classesName,
                            });
                        }
                        state.dataSource = [...dataSource];
                    }
                });
            };
            getStudents(null,null);
            const editableData: UnwrapRef < Record < string, DataItem >> = reactive({});
            const edit = (key: string) => {
                console.log(key);
                var student = dataSource.filter(item => key === item.key)[0];
                addEditFormState.id = student.id;
                addEditFormState.no = student.no;
                addEditFormState.name = student.name;
                addEditFormState.age = student.age;
                addEditFormState.sex = student.sexValue;
                addEditFormState.classes = student.classesId;
                visible.value = true;
                console.log(student);
            };
            const change = (pagination) => {
                var no = formState.no;
                var name = formState.name;
                getStudents(no, name);
                console.log(pagination);
            };
            const onSubmit = () => {
                console.log('submit!', toRaw(formState));
            };
            return {
                formState,
                addEditFormState,
                ...toRefs(state),
                columns,
                editingKey: '',
                editableData,
                edit,
                pagination,
                change,
                onFinish,
                onFinishFailed,
                onSubmit,
                visible,
                addStudent,
                handleOk,
                //modalTitleRef,
                //transformStyle,
            };
        },
    });
</script>
<style>
    .editable-row-operations a {
        margin-right: 8px;
    }
    .ant-form {
        height: 6vh;
        width: 100vh;
        background-color: transparent;
    }
    .ant-modal-content {
        height: 50vh;
    }
    .ant-modal-body .ant-input {
        width: 40vh;
    }
    .ant-modal-body {
        height: 40vh;
    }
    .ant-modal-body .ant-page-header {
        width: 46vh;
        padding: 0.5rem;
    }
</style>

示例截图


学生管理模块,示例截图如下所示:

备注


以上就是Vue3.0+Antdv+Asp.net WebApi开发学生信息管理系统第三篇的全部内容,写文不易,多谢支持。学习编程,从关注【老码识途】开始!!!

相关文章
|
9月前
|
开发框架 前端开发 JavaScript
VUE3.0+Antdv+Asp.net WebApi开发学生信息管理系统(完)
VUE3.0+Antdv+Asp.net WebApi开发学生信息管理系统(完)
78 0
|
开发框架 JavaScript 前端开发
ASP.NET WebApi+Vue前后端分离之允许启用跨域请求
ASP.NET WebApi+Vue前后端分离之允许启用跨域请求
277 0
|
开发框架 .NET Linux
ASP.NET Core微服务之Docker容器化WebAPI
Tip: 此篇已加入.NET Core微服务基础系列文章索引 一、Docker极简介绍 1.1 总体介绍   Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源。
4370 0
|
开发框架 JSON .NET
HttpClient 调用WebAPI时—传参的三种方式(ASP.NET MVC&CORE均适用)
HttpClient 调用WebAPI时—传参的三种方式(ASP.NET MVC&CORE均适用)
235 0
|
开发框架 .NET API
版本化ASP.NET Core WebApi
版本化ASP.NET Core WebApi
115 0
|
XML 开发框架 .NET
【原创】ASP.NET WebApi接收xml文件 xml序列化
如何新建WebApi项目就不用我介绍了吧。 直接进入正题。 首先,在.net平台不论要接收什么,肯定是从Request里获取。 大家肯定对普通的参数获取非常熟悉了,下面就介绍一下如何从Request获取文件流. System.IO.Stream sm =Request.Content.ReadAsStreamAsync().Result 这个方法返回的是一个System.IO.Stream类型,如果是单纯想获得文件,到这一步你就可以把它保存到本地了。
9110 0
|
XML 开发框架 JSON
ASP.NET Core - 实现自定义WebApi模型验证
ASP.NET Core - 实现自定义WebApi模型验证  Framework时代    在Framework时代,我们一般进行参数验证的时候,以下代码是非常常见的 复制代码 [HttpPost] public async Task<JsonResult> SaveNewCus...
1663 0
ASP.NET Core on K8S学习初探(2)部署WebAPI到K8S
本文首先主要快速地不完全地不求甚解地过了一下K8S中的一些重要的基本概念,然后通过kubectl部署一个ASP.NET Core WebAPI到K8S中,并初步使用了K8S的伸缩特性对Deployment进行实例的伸缩,体验了一下所谓的容器的编排。
2642 0

相关实验场景

更多