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表单。

查询功能

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

 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": name
19     }).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": 0
21     }).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: string
128     }
129     interface FormState {
130         no: string;
131         name: string;
132     }
133     interface ClassesItem {
134         id: number,
135             name: string
136     }
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": 0
188                 }).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: dataClasses
217             });
218             const getClasses=()=>{
219                 getD('/api/Classes/GetClassess', {
220                     "dept": "",
221                     "grade": "",
222                     "pageSize": 0,
223                     "pageNum": 0
224                 }).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": name
245                 }).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开发学生信息管理系统第三篇的全部内容,写文不易,多谢支持。学习编程,从关注【老码识途】开始!!!

posted @ 2022-08-17 21:36  老码识途呀  阅读(635)  评论(0编辑  收藏  举报