在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开发学生信息管理系统第三篇的全部内容,写文不易,多谢支持。学习编程,从关注【老码识途】开始!!!