在B/S系统开发中,前后端分离开发设计已成为一种标准,而VUE作为前端三大主流框架之一,越来越受到大家的青睐,Antdv是Antd在Vue中的实现。本系列文章主要通过Antdv和Asp.net WebApi开发学生信息管理系统,简述前后端分离开发的主要相关内容,仅供学习分享使用,如有不足之处,还请指正。.
什么是Antdv ?
Antdv【ant-design-vue】是Antd在Vue中的实现,为 Web 应用提供了丰富的基础 UI 组件,我们还将持续探索企业级应用的最佳 UI 实践。
在本示例项目中,主要包含两大部分:1.前端web项目【vsims.web】2.后端webapi项目【vsims.webapi】,本文先讲解前端web项目相关内容。
创建前端项目
通过命令vue create vsims.web 创建学生管理系统前端项目,在创建过程中,选择手动创建模式,选择Babel,TypeScript和Router等,如下所示:
安装Antdv组件
切换到项目目录,然后安装Antdv组件,命令如下:
npm i --save ant-design-vue
安装组件示例截图如下所示:
vsims.web项目组成
通过脚手架创建项目且安装Antdv组件后,在HbuilderX中打开,如下所示:
注册Antdv组件
在安装组件后,并不能直接使用,需要进行注册后,才可以在项目中使用,注册分为全局完整注册,全局部分注册,和局部注册,本文为了简便,采用全局完整注册的方式。
通过主文件【main.ts】进行注册,如下所示:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
//1. 引入Antdv组件和样式
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
const app = createApp(App);
app.use(router).use(Antd).mount('#app')
定制主题
由于本项目使用VUE3.0,所以定制主题,需要在项目中创建vue.config.js文件,然后添加主题配置代码,如下所示:
const {
defineConfig
} = require('@vue/cli-service')
module.exports = defineConfig({
css: {
loaderOptions: {
less: {
lessOptions: {
modifyVars: {
'primary-color': '#1DA57A',
'link-color': '#1DA57A',
'border-radius-base': '2px',
},
javascriptEnabled: true,
},
},
},
},
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
args[0].title = 'SIMS'
return args
})
},
transpileDependencies: true
})
运行项目(一)
在项目目录下,打开命令行,运行npm run serve启动项目,如下所示:
在浏览器中输入网址http://localhost:8080/,打开如下所示:
如上图所示,则表示上述配置成功。
添加路由视图
删除掉App.vue中默认生成的代码,然后添加路由视图【router-view】,代码如下所示:
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<style>
</style>
注意:因为路由在创建项目时已经添加,所以可以直接使用。
系统布局
在学生信息管理系统中,采用传统的上,中【左右】,下布局。在views视图文件中,新建HomeView.vue视图文件,如下所示:
<template>
<div id="layout">
<a-layout>
<a-layout-header>Header</a-layout-header>
<a-layout>
<a-layout-sider>Sider</a-layout-sider>
<a-layout-content>Content</a-layout-content>
</a-layout>
<a-layout-footer>Footer</a-layout-footer>
</a-layout>
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</script>
<style>
#app{
height: inherit;
}
#layout{
height: inherit;
}
.ant-layout{
height: inherit;
}
#layout .code-box-demo {
text-align: center;
}
#layout .ant-layout-header,
#layout .ant-layout-footer {
color: #fff;
background: #7dbcea;
}
[data-theme='dark'] #layout .ant-layout-header {
background: #6aa0c7;
}
[data-theme='dark'] #layout .ant-layout-footer {
background: #6aa0c7;
}
#layout .ant-layout-footer {
line-height: 1.5;
}
#layout .ant-layout-sider {
color: #fff;
line-height: 120px;
background: #3ba0e9;
}
[data-theme='dark'] #layout .ant-layout-sider {
background: #3499ec;
}
#layout .ant-layout-content {
min-height: 120px;
color: #fff;
line-height: 120px;
background: rgba(16, 142, 233, 1);
}
[data-theme='dark'] #layout .ant-layout-content {
background: #107bcb;
}
#layout>.code-box-demo>.ant-layout+.ant-layout {
margin-top: 48px;
}
</style>
重新打开浏览器,如下所示:
添加导航菜单
在默认布局中创建成功后,在左侧布局容器中,添加菜单内容,如下所示:
<a-layout-sider v-model:collapsed="collapsed">
<a-button type="primary" style="margin-bottom: 5px" @click="toggleCollapsed">
<MenuUnfoldOutlined v-if="collapsed" />
<MenuFoldOutlined v-else />
</a-button>
<a-menu v-model:openKeys="openKeys" v-model:selectedKeys="selectedKeys" mode="inline" theme="dark" :inline-collapsed="collapsed">
<a-menu-item key="1">
<template #icon><HomeOutlined /></template>
<router-link to="/main">首页</router-link>
</a-menu-item>
<a-sub-menu key="sub1">
<template #icon>
<ReadOutlined />
</template>
<template #title>
<span class="onemenu">学生管理</span>
</template>
<a-menu-item key="5">
<img src="../assets/icon_student.png" class="icon" />
<router-link to="/student">学生管理</router-link>
</a-menu-item>
<a-menu-item key="6">
<img src="../assets/icon_classes.png" class="icon" />
<router-link to="/classes">班级管理</router-link>
</a-menu-item>
<a-menu-item key="7">
<img src="../assets/icon_course.png" class="icon" />
<router-link to="/course">课程管理</router-link>
</a-menu-item>
<a-menu-item key="8">
<img src="../assets/icon_score.png" class="icon" />
<router-link to="score">成绩管理</router-link>
</a-menu-item>
</a-sub-menu>
<a-sub-menu key="sub2">
<template #icon>
<AppstoreOutlined />
</template>
<template #title>
<span class="onemenu">系统管理</span>
</template>
<a-menu-item key="9">
<img src="../assets/icon_personal.png" class="icon" />
<router-link to="/personal">个人信息</router-link>
</a-menu-item>
<a-menu-item key="10">
<img src="../assets/icon_user.png" class="icon" />
<router-link to="/user">用户管理</router-link>
</a-menu-item>
<a-menu-item key="11">
<img src="../assets/icon_role.png" class="icon" />
<router-link to="/role">角色管理</router-link>
</a-menu-item>
</a-sub-menu>
</a-menu>
</a-layout-sider>
在内容布局中,添加路由视图,作为二级视图,如下所示:
<a-layout-content>
<router-view></router-view>
</a-layout-content>
添加菜单对应的视图
根据系统设计,主要包含学生管理,成绩管理,班级管理,课程管理,以及系统管理等相关内容,每一个功能对应一个页面视图,如下所示:
每一个视图对应以路由,视图创建完成后,修改router\index.ts文件,添加路由,如下所示:
import%20{%20createRouter,%20createWebHistory,%20RouteRecordRaw%20}%20from%20'vue-router'
import%20HomeView%20from%20'../views/HomeView.vue'
import%20LoginView%20from%20'../views/LoginView.vue'
import%20MainView%20from%20'../views/MainView.vue'
import%20StudentView%20from%20'../views/StudentView.vue'
import%20ClassesView%20from%20'../views/ClassesView.vue'
import%20CourseView%20from%20'../views/CourseView.vue'
import%20ScoreView%20from%20'../views/ScoreView.vue'
import%20PersonalView%20from%20'../views/PersonalView.vue'
import%20MenuView%20from%20'../views/MenuView.vue'
import%20RoleView%20from%20'../views/RoleView.vue'
import%20UserView%20from%20'../views/UserView.vue'
const%20routes:%20Array<RouteRecordRaw>%20=%20[
%20%20{
%20%20%20%20path:%20'/',
%20%20%20%20name:%20'home1',
%20%20%20%20component:%20HomeView
%20%20},
%20%20{
%20%20%20%20path:%20'/home',
%20%20%20%20name:%20'home',
%20%20%20%20component:%20HomeView,
%20%20%20%20children:[
%20%20%20%20%20%20%20%20{
%20%20%20%20%20%20%20%20%20%20%20%20path:'/main',
%20%20%20%20%20%20%20%20%20%20%20%20name:'main',
%20%20%20%20%20%20%20%20%20%20%20%20component:MainView
%20%20%20%20%20%20%20%20},
%20%20%20%20%20%20%20%20{
%20%20%20%20%20%20%20%20%20%20%20%20path:'/student',
%20%20%20%20%20%20%20%20%20%20%20%20name:'student',
%20%20%20%20%20%20%20%20%20%20%20%20component:StudentView
%20%20%20%20%20%20%20%20},
%20%20%20%20%20%20%20%20{
%20%20%20%20%20%20%20%20%20%20%20%20path:'/classes',
%20%20%20%20%20%20%20%20%20%20%20%20name:'classes',
%20%20%20%20%20%20%20%20%20%20%20%20component:ClassesView
%20%20%20%20%20%20%20%20},
%20%20%20%20%20%20%20%20{
%20%20%20%20%20%20%20%20%20%20%20%20path:'/course',
%20%20%20%20%20%20%20%20%20%20%20%20name:'course',
%20%20%20%20%20%20%20%20%20%20%20%20component:CourseView
%20%20%20%20%20%20%20%20},
%20%20%20%20%20%20%20%20{
%20%20%20%20%20%20%20%20%20%20%20%20path:'/score',
%20%20%20%20%20%20%20%20%20%20%20%20name:'score',
%20%20%20%20%20%20%20%20%20%20%20%20component:ScoreView
%20%20%20%20%20%20%20%20},
%20%20%20%20%20%20%20%20{
%20%20%20%20%20%20%20%20%20%20%20%20path:'/personal',
%20%20%20%20%20%20%20%20%20%20%20%20name:'personal',
%20%20%20%20%20%20%20%20%20%20%20%20component:PersonalView
%20%20%20%20%20%20%20%20},
%20%20%20%20%20%20%20%20{
%20%20%20%20%20%20%20%20%20%20%20%20path:'/menu',
%20%20%20%20%20%20%20%20%20%20%20%20name:'menu',
%20%20%20%20%20%20%20%20%20%20%20%20component:MenuView
%20%20%20%20%20%20%20%20},
%20%20%20%20%20%20%20%20{
%20%20%20%20%20%20%20%20%20%20%20%20path:'/user',
%20%20%20%20%20%20%20%20%20%20%20%20name:'user',
%20%20%20%20%20%20%20%20%20%20%20%20component:UserView
%20%20%20%20%20%20%20%20},
%20%20%20%20%20%20%20%20{
%20%20%20%20%20%20%20%20%20%20%20%20path:'/role',
%20%20%20%20%20%20%20%20%20%20%20%20name:'role',
%20%20%20%20%20%20%20%20%20%20%20%20component:RoleView
%20%20%20%20%20%20%20%20}
%20%20%20%20]
%20%20},
%20%20{
%20%20%20%20path:'/login',
%20%20%20%20name:'login',
%20%20%20%20component:LoginView
%20%20},
]
const%20router%20=%20createRouter({
%20%20history:%20createWebHistory(process.env.BASE_URL),
%20%20routes
})
export%20default%20router
创建登录视图
在学生信息管理系统中,进入主页面之前,需要先进行登录,如下所示,
<template>
%20%20%20%20<div%20id="login">
%20%20%20%20%20%20%20%20<a-form%20:model="formState"%20name="basic"%20:label-col="{%20span:%208%20}"%20:wrapper-col="{%20span:%2016%20}"%20autocomplete="off"%20@finish="onFinish"%20@finishFailed="onFinishFailed">
%20%20%20%20%20%20%20%20%20%20%20%20<div%20id="title">
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20<h1>学生信息管理系统</h1>
%20%20%20%20%20%20%20%20%20%20%20%20</div>
%20%20%20%20%20%20%20%20%20%20%20%20<a-form-item%20label="Username"%20name="username"%20:rules="[{%20required:%20true,%20message:%20'Please%20input%20your%20username!'%20}]">
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20<a-input%20v-model:value="formState.username"%20/>
%20%20%20%20%20%20%20%20%20%20%20%20</a-form-item>
%20%20%20%20%20%20%20%20%20%20%20%20<a-form-item%20label="Password"%20name="password"%20:rules="[{%20required:%20true,%20message:%20'Please%20input%20your%20password!'%20}]">
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20<a-input-password%20v-model:value="formState.password"%20/>
%20%20%20%20%20%20%20%20%20%20%20%20</a-form-item>
%20%20%20%20%20%20%20%20%20%20%20%20<a-form-item%20name="remember"%20:wrapper-col="{%20offset:%208,%20span:%2016%20}">
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20<a-checkbox%20v-model:checked="formState.remember">Remember%20me</a-checkbox>
%20%20%20%20%20%20%20%20%20%20%20%20</a-form-item>
%20%20%20%20%20%20%20%20%20%20%20%20<a-form-item%20:wrapper-col="{%20offset:%208,%20span:%2016%20}">
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20<a-button%20style="margin-right:%2010px;">Cancel</a-button>
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20<a-button%20type="primary"%20html-type="submit">Submit</a-button>
%20%20%20%20%20%20%20%20%20%20%20%20</a-form-item>
%20%20%20%20%20%20%20%20</a-form>
%20%20%20%20</div>
</template>
<script%20lang="ts">
%20%20%20%20import%20{
%20%20%20%20%20%20%20%20defineComponent,
%20%20%20%20%20%20%20%20reactive,
%20%20%20%20}%20from%20'vue';
%20%20%20%20import%20{
%20%20%20%20%20%20%20%20useRouter,
%20%20%20%20%20%20%20%20//useRoute
%20%20%20%20}%20from%20'vue-router'
%20%20%20%20interface%20FormState%20{
%20%20%20%20%20%20%20%20username:%20string;
%20%20%20%20%20%20%20%20password:%20string;
%20%20%20%20%20%20%20%20remember:%20boolean;
%20%20%20%20}
%20%20%20%20export%20default%20defineComponent({
%20%20%20%20%20%20%20%20setup()%20{
%20%20%20%20%20%20%20%20%20%20%20%20const%20router%20=%20useRouter();
%20%20%20%20%20%20%20%20%20%20%20%20//const%20route=%20useRoute();
%20%20%20%20%20%20%20%20%20%20%20%20const%20formState%20=%20reactive%20<%20FormState%20>%20({
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20username:%20'',
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20password:%20'',
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20remember:%20true,
%20%20%20%20%20%20%20%20%20%20%20%20});
%20%20%20%20%20%20%20%20%20%20%20%20const%20onFinish%20=%20(values:%20any)%20=>%20{
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20console.log(values);
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20console.log('Success:',%20values);
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20router.push('/home');
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//this.$router.push('/home');
%20%20%20%20%20%20%20%20%20%20%20%20};
%20%20%20%20%20%20%20%20%20%20%20%20const%20onFinishFailed%20=%20(errorInfo:%20any)%20=>%20{
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20console.log('Failed:',%20errorInfo);
%20%20%20%20%20%20%20%20%20%20%20%20};
%20%20%20%20%20%20%20%20%20%20%20%20return%20{
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20formState,
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20onFinish,
%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20onFinishFailed,
%20%20%20%20%20%20%20%20%20%20%20%20};
%20%20%20%20%20%20%20%20},
%20%20%20%20});
</script>
<style>
%20%20%20%20body{
%20%20%20%20%20%20%20%20background-image:%20url(../assets/bg.gif);
background-repeat: no-repeat;
background-size: 100% 100%;
}
#login{
position: absolute;
left: 35%;
top: 30%;
}
#title h1{
color: #FFFFFF;
}
.ant-form{
width: 60vh;
height: 35vh;
background-color:rgba(10,10,10,0.2);
padding: 0.625rem !important;
}
</style>
运行项目(二)
当系统搭建完成后,启动项目,然后在浏览器中打开,如下所示:
以上就是Antdv+Asp.net WebApi开发学生信息管理系统的开篇介绍,因为是前后端分离项目,还未涉及到后端内容,所以有些是写成固定值,后续会进一步优化成动态加载内容。