在B/S系统开发中,前后端分离开发设计已成为一种标准,而VUE作为前端三大主流框架之一,越来越受到大家的青睐,Antdv是Antd在Vue中的实现。本系列文章主要通过Antdv和Asp.net WebApi开发学生信息管理系统,简述前后端分离开发的主要相关内容,仅供学习分享使用,如有不足之处,还请指正。
在本示例项目中,主要包含两大部分:1.前端web项目【vsims.web】2.后端webapi项目【vsims.webapi】,本文先讲解前端web项目相关内容。
通过命令vue create vsims.web 创建学生管理系统前端项目,在创建过程中,选择手动创建模式,选择Babel,TypeScripe和Router等,如下所示:

切换到项目目录,然后安装Antdv组件,命令如下:
1 npm i --save ant-design-vue
安装组件示例截图如下所示:
通过脚手架创建项目且安装Antdv组件后,在HbuilderX中打开,如下所示:

在安装组件后,并不能直接使用,需要进行注册后,才可以在项目中使用,注册分为全局完整注册,全局部分注册,和局部注册,本文为了简便,采用全局完整注册的方式。
通过主文件【main.js】进行注册,如下所示:
1 import { createApp } from 'vue'
2 import App from './App.vue'
3 import router from './router'
4 //1. 引入Antdv组件和样式
5 import Antd from 'ant-design-vue';
6 import 'ant-design-vue/dist/antd.css';
7 const app = createApp(App);
8 app.use(router).use(Antd).mount('#app')
由于本项目使用VUE3.0,所以定制主题,需要在项目中创建vue.config.js文件,然后添加主题配置代码,如下所示:
1 const {
2 defineConfig
3 } = require('@vue/cli-service')
4 module.exports = defineConfig({
5 css: {
6 loaderOptions: {
7 less: {
8 lessOptions: {
9 modifyVars: {
10 'primary-color': '#1DA57A',
11 'link-color': '#1DA57A',
12 'border-radius-base': '2px',
13 },
14 javascriptEnabled: true,
15 },
16 },
17 },
18 },
19 chainWebpack: config => {
20 config
21 .plugin('html')
22 .tap(args => {
23 args[0].title = 'SIMS'
24 return args
25 })
26 },
27 transpileDependencies: true
28 })
在项目目录下,打开命令行,运行npm run serve启动项目,如下所示:

在浏览器中输入网址http://localhost:8080/,打开如下所示:

如上图所示,则表示上述配置成功。
删除掉App.vue中默认生成的代码,然后添加路由视图【router-view】,代码如下所示:
1 <template>
2 <div id="app">
3 <router-view></router-view>
4 </div>
5 </template>
6 <style>
7
8 </style>
注意:因为路由在创建项目时已经添加,所以可以直接使用。
在学生信息管理系统中,采用传统的上,中【左右】,下布局。在views视图文件中,新建HomeView.vue视图文件,如下所示:
1 <template>
2 <div id="layout">
3 <a-layout>
4 <a-layout-header>Header</a-layout-header>
5 <a-layout>
6 <a-layout-sider>Sider</a-layout-sider>
7 <a-layout-content>Content</a-layout-content>
8 </a-layout>
9 <a-layout-footer>Footer</a-layout-footer>
10 </a-layout>
11 </div>
12 </template>
13
14 <script>
15 export default {
16 name: 'App',
17 components: {
18
19 }
20 }
21 </script>
22
23 <style>
24 #app{
25 height: inherit;
26 }
27 #layout{
28 height: inherit;
29 }
30 .ant-layout{
31 height: inherit;
32 }
33 #layout .code-box-demo {
34 text-align: center;
35 }
36
37 #layout .ant-layout-header,
38 #layout .ant-layout-footer {
39 color: #fff;
40 background: #7dbcea;
41 }
42
43 [data-theme='dark'] #layout .ant-layout-header {
44 background: #6aa0c7;
45 }
46
47 [data-theme='dark'] #layout .ant-layout-footer {
48 background: #6aa0c7;
49 }
50
51 #layout .ant-layout-footer {
52 line-height: 1.5;
53 }
54
55 #layout .ant-layout-sider {
56 color: #fff;
57 line-height: 120px;
58 background: #3ba0e9;
59 }
60
61 [data-theme='dark'] #layout .ant-layout-sider {
62 background: #3499ec;
63 }
64
65 #layout .ant-layout-content {
66 min-height: 120px;
67 color: #fff;
68 line-height: 120px;
69 background: rgba(16, 142, 233, 1);
70 }
71
72 [data-theme='dark'] #layout .ant-layout-content {
73 background: #107bcb;
74 }
75
76 #layout>.code-box-demo>.ant-layout+.ant-layout {
77 margin-top: 48px;
78 }
79 </style>
重新打开浏览器,如下所示:

在默认布局中创建成功后,在左侧布局容器中,添加菜单内容,如下所示:
1 <a-layout-sider v-model:collapsed="collapsed">
2 <a-button type="primary" style="margin-bottom: 5px" @click="toggleCollapsed">
3 <MenuUnfoldOutlined v-if="collapsed" />
4 <MenuFoldOutlined v-else />
5 </a-button>
6 <a-menu v-model:openKeys="openKeys" v-model:selectedKeys="selectedKeys" mode="inline" theme="dark" :inline-collapsed="collapsed">
7 <a-menu-item key="1">
8 <template #icon><HomeOutlined /></template>
9 <router-link to="/main">首页</router-link>
10 </a-menu-item>
11 <a-sub-menu key="sub1">
12 <template #icon>
13 <ReadOutlined />
14 </template>
15 <template #title>
16 <span class="onemenu">学生管理</span>
17 </template>
18 <a-menu-item key="5">
19 <img src="../assets/icon_student.png" class="icon" />
20 <router-link to="/student">学生管理</router-link>
21 </a-menu-item>
22 <a-menu-item key="6">
23 <img src="../assets/icon_classes.png" class="icon" />
24 <router-link to="/classes">班级管理</router-link>
25 </a-menu-item>
26 <a-menu-item key="7">
27 <img src="../assets/icon_course.png" class="icon" />
28 <router-link to="/course">课程管理</router-link>
29 </a-menu-item>
30 <a-menu-item key="8">
31 <img src="../assets/icon_score.png" class="icon" />
32 <router-link to="score">成绩管理</router-link>
33 </a-menu-item>
34 </a-sub-menu>
35 <a-sub-menu key="sub2">
36 <template #icon>
37 <AppstoreOutlined />
38 </template>
39 <template #title>
40 <span class="onemenu">系统管理</span>
41 </template>
42 <a-menu-item key="9">
43 <img src="../assets/icon_personal.png" class="icon" />
44 <router-link to="/personal">个人信息</router-link>
45 </a-menu-item>
46 <a-menu-item key="10">
47 <img src="../assets/icon_user.png" class="icon" />
48 <router-link to="/user">用户管理</router-link>
49 </a-menu-item>
50 <a-menu-item key="11">
51 <img src="../assets/icon_role.png" class="icon" />
52 <router-link to="/role">角色管理</router-link>
53 </a-menu-item>
54 </a-sub-menu>
55 </a-menu>
56 </a-layout-sider>
在内容布局中,添加路由视图,作为二级视图,如下所示:
1 <a-layout-content>
2 <router-view></router-view>
3 </a-layout-content>
添加菜单对应的视图
根据系统设计,主要包含学生管理,成绩管理,班级管理,课程管理,以及系统管理等相关内容,每一个功能对应一个页面视图,如下所示:
每一个视图对应以路由,视图创建完成后,修改router\index.ts文件,添加路由,如下所示:
1 import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
2 import HomeView from '../views/HomeView.vue'
3 import LoginView from '../views/LoginView.vue'
4 import MainView from '../views/MainView.vue'
5 import StudentView from '../views/StudentView.vue'
6 import ClassesView from '../views/ClassesView.vue'
7 import CourseView from '../views/CourseView.vue'
8 import ScoreView from '../views/ScoreView.vue'
9 import PersonalView from '../views/PersonalView.vue'
10 import MenuView from '../views/MenuView.vue'
11 import RoleView from '../views/RoleView.vue'
12 import UserView from '../views/UserView.vue'
13
14 const routes: Array<RouteRecordRaw> = [
15 {
16 path: '/',
17 name: 'home1',
18 component: HomeView
19 },
20 {
21 path: '/home',
22 name: 'home',
23 component: HomeView,
24 children:[
25 {
26 path:'/main',
27 name:'main',
28 component:MainView
29 },
30 {
31 path:'/student',
32 name:'student',
33 component:StudentView
34 },
35 {
36 path:'/classes',
37 name:'classes',
38 component:ClassesView
39 },
40 {
41 path:'/course',
42 name:'course',
43 component:CourseView
44 },
45 {
46 path:'/score',
47 name:'score',
48 component:ScoreView
49 },
50 {
51 path:'/personal',
52 name:'personal',
53 component:PersonalView
54 },
55 {
56 path:'/menu',
57 name:'menu',
58 component:MenuView
59 },
60 {
61 path:'/user',
62 name:'user',
63 component:UserView
64 },
65 {
66 path:'/role',
67 name:'role',
68 component:RoleView
69 }
70 ]
71 },
72 {
73 path:'/login',
74 name:'login',
75 component:LoginView
76 },
77
78 ]
79
80 const router = createRouter({
81 history: createWebHistory(process.env.BASE_URL),
82 routes
83 })
84
85 export default router
在学生信息管理系统中,进入主页面之前,需要先进行登录,如下所示,
1 <template>
2 <div id="login">
3 <a-form :model="formState" name="basic" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }" autocomplete="off" @finish="onFinish" @finishFailed="onFinishFailed">
4 <div id="title">
5 <h1>学生信息管理系统</h1>
6 </div>
7 <a-form-item label="Username" name="username" :rules="[{ required: true, message: 'Please input your username!' }]">
8 <a-input v-model:value="formState.username" />
9 </a-form-item>
10
11 <a-form-item label="Password" name="password" :rules="[{ required: true, message: 'Please input your password!' }]">
12 <a-input-password v-model:value="formState.password" />
13 </a-form-item>
14
15 <a-form-item name="remember" :wrapper-col="{ offset: 8, span: 16 }">
16 <a-checkbox v-model:checked="formState.remember">Remember me</a-checkbox>
17 </a-form-item>
18
19 <a-form-item :wrapper-col="{ offset: 8, span: 16 }">
20 <a-button style="margin-right: 10px;">Cancel</a-button>
21 <a-button type="primary" html-type="submit">Submit</a-button>
22 </a-form-item>
23 </a-form>
24 </div>
25 </template>
26 <script lang="ts">
27 import {
28 defineComponent,
29 reactive,
30 } from 'vue';
31 import {
32 useRouter,
33 //useRoute
34 } from 'vue-router'
35
36 interface FormState {
37 username: string;
38 password: string;
39 remember: boolean;
40 }
41 export default defineComponent({
42 setup() {
43 const router = useRouter();
44 //const route= useRoute();
45 const formState = reactive < FormState > ({
46 username: '',
47 password: '',
48 remember: true,
49 });
50 const onFinish = (values: any) => {
51 console.log(values);
52 console.log('Success:', values);
53 router.push('/home');
54 //this.$router.push('/home');
55 };
56
57 const onFinishFailed = (errorInfo: any) => {
58 console.log('Failed:', errorInfo);
59 };
60 return {
61 formState,
62 onFinish,
63 onFinishFailed,
64 };
65 },
66 });
67 </script>
68 <style>
69 body{
70 background-image: url(../assets/bg.gif);
71 background-repeat: no-repeat;
72 background-size: 100% 100%;
73 }
74 #login{
75 position: absolute;
76 left: 35%;
77 top: 30%;
78 }
79 #title h1{
80 color: #FFFFFF;
81 }
82 .ant-form{
83 width: 60vh;
84 height: 35vh;
85 background-color:rgba(10,10,10,0.2);
86 padding: 0.625rem !important;
87 }
88 </style>
当系统搭建完成后,启动项目,然后在浏览器中打开,如下所示:

以上就是Antdv+Asp.net WebApi开发学生信息管理系统的开篇介绍,因为是前后端分离项目,还未涉及到后端内容,所以有些是写成固定值,后续会进一步优化成动态加载内容。
新的开始,新的篇章。学习编程,从关注【老码识途】开始!!!

我正在使用i18n从头开始构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在rubyonrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI
我安装了ruby版本管理器,并将RVM安装的ruby实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby。有没有办法让emacs像shell一样尊重ruby的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el
这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub
我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain
是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s