在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表单。
查询功能
在学生管理模块中,查询功能主要通过学号,姓名两个条件进行查询,代码如下所示:
1 <a-form :model="formState" name="horizontal_query" layout="inline" autocomplete="off" @finish="onFinish" @finishFailed="onFinishFailed"> 2 <a-form-item label="学号" name="no"> 3 <a-input v-model:value="formState.no"></a-input> 4 </a-form-item> 5 <a-form-item label="姓名" name="name"> 6 <a-input v-model:value="formState.name"></a-input> 7 </a-form-item> 8 <a-form-item> 9 <a-button type="primary" html-type="submit">查询</a-button>10 </a-form-item>11 <a-form-item>12 <a-button type="primary" @click="addStudent">新增</a-button>13 </a-form-item>14 </a-form>
注意:form表单的提交事件为submit,finish为提交成功后的响应事件,在此事件中可以进行接口调用,如下所示:
1 const onFinish = (values: any) => { 2 var no = values.no; 3 var name = values.name; 4 getStudents(no, name); 5 console.log('Success:', values); 6 }; 7 8 const onFinishFailed = (errorInfo: any) => { 9 console.log('Failed:', errorInfo);10 };11 12 const getStudents = (no, name) => {13 dataSource.length = 0;14 getD('/api/Student/GetStudents', {15 "pageSize": pagination.pageSize,16 "pageNum": pagination.current,17 "no": no,18 "name": name19 }).then(res => {20 console.log(res);21 if (res.status == 200) {22 pagination.total = res.data.count; //总记录数23 console.log(pagination.total);24 for (let i = 0; i < res.data.items.length; i++) {25 dataSource.push({26 id: res.data.items[i].id,27 key: res.data.items[i].id.toString(),28 no: res.data.items[i].no,29 name: res.data.items[i].name,30 age: res.data.items[i].age,31 sex: res.data.items[i].sex ? "男" : "女",32 sexValue: res.data.items[i].sex,33 classesId: res.data.items[i].classesId,34 classesName: res.data.items[i].classesName,35 });36 }37 state.dataSource = [...dataSource];38 }39 });40 };
其中getStudents方法,多个地方会进行调用,所以进行了封装,主要用于学生列表查询接口访问。
数据展示
数据展示主要使用a-table控件,其中columns定义需要显示的列,data-source绑定数据源,如下所示:
1 <a-table :columns="columns" :data-source="dataSource" bordered :pagination="false" :row-key="record => record.id"> 2 <template #bodyCell="{ column, text, record }"> 3 <template v-if="[ 'no','name', 'sge', 'dex','classesName'].includes(column.dataIndex)"> 4 <div>{{ text }}</div> 5 </template> 6 <template v-else-if="column.dataIndex === 'operation'"> 7 <div class="editable-row-operations"> 8 <a @click="edit(record.key)">Edit</a> 9 </div>10 </template>11 </template>12 </a-table>
注意:默认情况下,当数据源发生更新时,a-table控件不会信息页面刷新,需要绑定row-key属性才可以。
分页功能
分页功能主要才用分页控件a-pagination,其中current表示当前页,total表示总页码,change表示绑定分页事件,如下所示:
1 <a-pagination v-model:current="pagination.current" :total="pagination.total" @change="change" />
关于change事件功能,主要用于调用getStudents函数,如下所示:
1 const change = (pagination) => {2 var no = formState.no;3 var name = formState.name;4 getStudents(no, name);5 console.log(pagination);6 };
新增编辑功能
新增学生和编辑学生都是对单个学生实体进行操作,采用form表单进行提交到后台接口。其中visible用于控制弹窗的显示与隐藏。ok表示弹窗的确定事件。班级下拉框(a-select)显示班级列表,需要在加载页面时进行预加载。如下所示:
1 <a-modal ref="modalRef" v-model:visible="visible" okText="保存" cancelText="取消" :wrap-style="{ overflow: 'hidden' }" @ok="handleOk"> 2 <div> 3 <a-page-header style="border: 1px solid rgb(235, 237, 240)" title="学生管理" sub-title="新增或编辑学生" /> 4 <a-form :model="addEditFormState"> 5 <a-form-item label="学号"> 6 <a-input v-model:value="addEditFormState.no" /> 7 </a-form-item> 8 <a-form-item label="姓名"> 9 <a-input v-model:value="addEditFormState.name" />10 </a-form-item>11 <a-form-item label="年龄">12 <a-input v-model:value="addEditFormState.age" />13 </a-form-item>14 <a-form-item label="性别">15 <a-radio-group v-model:value="addEditFormState.sex">16 <a-radio :value="true">男</a-radio>17 <a-radio :value="false">女</a-radio>18 </a-radio-group>19 </a-form-item>20 <a-form-item label="班级">21 <a-select ref="select" v-model:value="addEditFormState.classes" style="width: 200px">22 <a-select-option :value="item.id" v-for="(item) in dataClasses" :key="item.id">{{item.name}}</a-select-option>23 </a-select>24 </a-form-item>25 </a-form>26 </div>27 </a-modal>
新增编辑提交事件handleOk代码,其中根据id值判断是新增学生和编辑学生,如下所示:
1 const handleOk = (e: MouseEvent) => { 2 console.log(e); 3 console.log(addEditFormState); 4 var url = ""; 5 if (addEditFormState.id >0) { 6 url = "/api/Student/UpdateStudent"; //编辑 7 } else { 8 url = "/api/Student/AddStudent"; //新增 9 }10 postD(url, {11 "id": addEditFormState.id>0?addEditFormState.id:null,12 "no": addEditFormState.no,13 "name": addEditFormState.name,14 "age": addEditFormState.age,15 "sex": addEditFormState.sex,16 "classesId": addEditFormState.classes,17 "createTime": "2022-08-15T15:31:12.224Z",18 "createUser": 0,19 "lastEditTime": "2022-08-15T15:31:12.224Z",20 "lastEditUser": 021 }).then(res => {22 console.log(res);23 if(res.status==200){24 if(res.data==0){25 message.success('保存成功!');26 visible.value = false;27 var no = formState.no;28 var name = formState.name;29 getStudents(no, name);30 }else{31 message.error('保存失败!');32 }33 }34 });35 36 };
关于学生管理模块的全部代码,如下所示:
1 <template> 2 <a-page-header style="border: 1px solid rgb(235, 237, 240)" title="学生管理" sub-title="学生信息基本操作" /> 3 <a-form :model="formState" name="horizontal_query" layout="inline" autocomplete="off" @finish="onFinish" @finishFailed="onFinishFailed"> 4 <a-form-item label="学号" name="no"> 5 <a-input v-model:value="formState.no"></a-input> 6 </a-form-item> 7 <a-form-item label="姓名" name="name"> 8 <a-input v-model:value="formState.name"></a-input> 9 </a-form-item> 10 <a-form-item> 11 <a-button type="primary" html-type="submit">查询</a-button> 12 </a-form-item> 13 <a-form-item> 14 <a-button type="primary" @click="addStudent">新增</a-button> 15 </a-form-item> 16 </a-form> 17 <a-table :columns="columns" :data-source="dataSource" bordered :pagination="false" :row-key="record => record.id"> 18 <template #bodyCell="{ column, text, record }"> 19 <template v-if="[ 'no','name', 'sge', 'dex','classesName'].includes(column.dataIndex)"> 20 <div>{{ text }}</div> 21 </template> 22 <template v-else-if="column.dataIndex === 'operation'"> 23 <div class="editable-row-operations"> 24 <a @click="edit(record.key)">Edit</a> 25 </div> 26 </template> 27 </template> 28 </a-table> 29 <a-pagination v-model:current="pagination.current" :total="pagination.total" @change="change" /> 30 <a-modal ref="modalRef" v-model:visible="visible" okText="保存" cancelText="取消" :wrap-style="{ overflow: 'hidden' }" @ok="handleOk"> 31 <div> 32 <a-page-header style="border: 1px solid rgb(235, 237, 240)" title="学生管理" sub-title="新增或编辑学生" /> 33 <a-form :model="addEditFormState"> 34 <a-form-item label="学号"> 35 <a-input v-model:value="addEditFormState.no" /> 36 </a-form-item> 37 <a-form-item label="姓名"> 38 <a-input v-model:value="addEditFormState.name" /> 39 </a-form-item> 40 <a-form-item label="年龄"> 41 <a-input v-model:value="addEditFormState.age" /> 42 </a-form-item> 43 <a-form-item label="性别"> 44 <a-radio-group v-model:value="addEditFormState.sex"> 45 <a-radio :value="true">男</a-radio> 46 <a-radio :value="false">女</a-radio> 47 </a-radio-group> 48 </a-form-item> 49 <a-form-item label="班级"> 50 <a-select ref="select" v-model:value="addEditFormState.classes" style="width: 200px"> 51 <a-select-option :value="item.id" v-for="(item) in dataClasses" :key="item.id">{{item.name}}</a-select-option> 52 </a-select> 53 </a-form-item> 54 </a-form> 55 </div> 56 </a-modal> 57 </template> 58 <script lang="ts"> 59 import { 60 defineComponent, 61 reactive, 62 toRefs, 63 ref, 64 toRaw 65 } from 'vue'; 66 import type { 67 UnwrapRef 68 } from 'vue'; 69 import { message } from 'ant-design-vue'; 70 import { 71 getD, 72 postD 73 } from '../api/index.js'; 74 75 const columns = [ 76 { 77 title: '学号', 78 dataIndex: 'no', 79 key: 'no', 80 align: 'center', 81 width: '20%', 82 }, 83 { 84 title: '姓名', 85 dataIndex: 'name', 86 key: 'name', 87 align: 'center', 88 width: '20%', 89 }, 90 { 91 title: '年龄', 92 dataIndex: 'age', 93 key: 'age', 94 align: 'center', 95 width: '15%', 96 }, 97 { 98 title: '性别', 99 dataIndex: 'sex',100 key: 'sex',101 align: 'center',102 width: '10%',103 },104 {105 title: '班级',106 dataIndex: 'classesName',107 key: 'classesName',108 align: 'center',109 width: '20%',110 },111 {112 title: '操作',113 dataIndex: 'operation',114 key: 'operation',115 align: 'center',116 },117 ];118 interface DataItem {119 id: number,120 key: string,121 no: string,122 name: string,123 age: number,124 sex: string,125 sexValue: boolean,126 classesId: string,127 classesName: string128 }129 interface FormState {130 no: string;131 name: string;132 }133 interface ClassesItem {134 id: number,135 name: string136 }137 const pagination = {138 total: 1,139 current: 1,140 pageSize: 10,141 };142 const dataClasses: ClassesItem[] = []; //班级列表143 const dataSource: DataItem[] = [];144 export default defineComponent({145 setup() {146 const formState = reactive < FormState > ({147 no: '',148 name: '',149 });150 const addEditFormState = reactive({151 id: 0,152 no: '',153 name: '',154 age: 0,155 sex: false,156 classes: '',157 });158 const visible = ref < boolean > (false);159 const addStudent = () => {160 addEditFormState.id = -1;161 addEditFormState.no = '';162 addEditFormState.name = '';163 addEditFormState.age = 0;164 addEditFormState.classes = '';165 visible.value = true;166 };167 168 const handleOk = (e: MouseEvent) => {169 console.log(e);170 console.log(addEditFormState);171 var url = "";172 if (addEditFormState.id >0) {173 url = "/api/Student/UpdateStudent"; //编辑174 } else {175 url = "/api/Student/AddStudent"; //新增176 }177 postD(url, {178 "id": addEditFormState.id>0?addEditFormState.id:null,179 "no": addEditFormState.no,180 "name": addEditFormState.name,181 "age": addEditFormState.age,182 "sex": addEditFormState.sex,183 "classesId": addEditFormState.classes,184 "createTime": "2022-08-15T15:31:12.224Z",185 "createUser": 0,186 "lastEditTime": "2022-08-15T15:31:12.224Z",187 "lastEditUser": 0188 }).then(res => {189 console.log(res);190 if(res.status==200){191 if(res.data==0){192 message.success('保存成功!');193 visible.value = false;194 var no = formState.no;195 var name = formState.name;196 getStudents(no, name);197 }else{198 message.error('保存失败!');199 }200 }201 });202 203 };204 const onFinish = (values: any) => {205 var no = values.no;206 var name = values.name;207 getStudents(no, name);208 console.log('Success:', values);209 };210 211 const onFinishFailed = (errorInfo: any) => {212 console.log('Failed:', errorInfo);213 };214 const state = reactive({215 dataSource: dataSource,216 dataClasses: dataClasses217 });218 const getClasses=()=>{219 getD('/api/Classes/GetClassess', {220 "dept": "",221 "grade": "",222 "pageSize": 0,223 "pageNum": 0224 }).then(res => {225 console.log(res);226 if (res.status == 200) {227 for (let i = 0; i < res.data.items.length; i++) {228 dataClasses.push({229 id: res.data.items[i].id,230 name: res.data.items[i].dept +res.data.items[i].grade+ res.data.items[i].name,231 });232 }233 state.dataClasses = [...dataClasses];234 }235 });236 };237 getClasses();238 const getStudents = (no, name) => {239 dataSource.length = 0;240 getD('/api/Student/GetStudents', {241 "pageSize": pagination.pageSize,242 "pageNum": pagination.current,243 "no": no,244 "name": name245 }).then(res => {246 console.log(res);247 if (res.status == 200) {248 pagination.total = res.data.count; //总记录数249 console.log(pagination.total);250 for (let i = 0; i < res.data.items.length; i++) {251 dataSource.push({252 id: res.data.items[i].id,253 key: res.data.items[i].id.toString(),254 no: res.data.items[i].no,255 name: res.data.items[i].name,256 age: res.data.items[i].age,257 sex: res.data.items[i].sex ? "男" : "女",258 sexValue: res.data.items[i].sex,259 classesId: res.data.items[i].classesId,260 classesName: res.data.items[i].classesName,261 });262 }263 state.dataSource = [...dataSource];264 }265 });266 };267 getStudents(null,null);268 const editableData: UnwrapRef < Record < string, DataItem >> = reactive({});269 270 const edit = (key: string) => {271 console.log(key);272 var student = dataSource.filter(item => key === item.key)[0];273 addEditFormState.id = student.id;274 addEditFormState.no = student.no;275 addEditFormState.name = student.name;276 addEditFormState.age = student.age;277 addEditFormState.sex = student.sexValue;278 addEditFormState.classes = student.classesId;279 visible.value = true;280 console.log(student);281 };282 283 const change = (pagination) => {284 var no = formState.no;285 var name = formState.name;286 getStudents(no, name);287 console.log(pagination);288 };289 const onSubmit = () => {290 console.log('submit!', toRaw(formState));291 };292 return {293 formState,294 addEditFormState,295 ...toRefs(state),296 columns,297 editingKey: '',298 editableData,299 edit,300 pagination,301 change,302 onFinish,303 onFinishFailed,304 onSubmit,305 visible,306 addStudent,307 handleOk,308 //modalTitleRef,309 //transformStyle,310 };311 },312 });313 </script>314 <style>315 .editable-row-operations a {316 margin-right: 8px;317 }318 319 .ant-form {320 height: 6vh;321 width: 100vh;322 background-color: transparent;323 }324 325 .ant-modal-content {326 height: 50vh;327 }328 329 .ant-modal-body .ant-input {330 width: 40vh;331 }332 333 .ant-modal-body {334 height: 40vh;335 }336 337 .ant-modal-body .ant-page-header {338 width: 46vh;339 padding: 0.5rem;340 }341 </style>
View Code
示例截图
学生管理模块,示例截图如下所示:
备注
以上就是Antdv+Asp.net WebApi开发学生信息管理系统第三篇的全部内容,写文不易,多谢支持。学习编程,从关注【老码识途】开始!!!