源码在本人博客资源当中,本文为项目代码的详细介绍解释,供于大家学习使用 Vue项目的入口文件:mian.js //vue项目入口文件//导入vueimport Vue from 'vue'//导入根组
源码在本人博客资源当中,本文为项目代码的详细介绍解释,供于大家学习使用
//vue项目入口文件//导入vueimport Vue from 'vue'//导入根组件appimport App from './App'//导入路由文件import router from './router'//导入ElementUIimport ElementUI from 'element-ui'import 'element-ui/lib/theme-chalk/index.CSS'//导入axiOSimport axios from "axios";import VueAxios from "vue-axios";import mavonEditor from 'mavon-editor'import 'mavon-editor/dist/css/index.css'// useVue.use(mavonEditor)//在vue当中挂载elementUI和axiosVue.use(ElementUI)Vue.use(VueAxios, axios)//productionTip设置为 false ,可以阻止 vue 在启动时生成生产提示Vue.config.productionTip = false// axios请求拦截器axios.interceptors.request.use(function (config) { // 在发送请求之前做些什么,例如加入token if (sessionStorage.getItem("auth") !== null) { config.headers.auth = sessionStorage.getItem("auth"); } return config;}, function (error) { // 对请求错误做些什么 return Promise.reject(error);});// axios响应拦截器axios.interceptors.response.use(function (response) { // 在接收响应做些什么,例如跳转到登录页 if (response.data.data === "没有登录") { response.data.success = true; router.push("/login"); } return response;}, function (error) { // 对响应错误做点什么 return Promise.reject(error);});//创建vue对象new Vue({ el: '#app', router, components: { App }, template: ' '})
这里唯一的难点就是axios请求拦截器和响应拦截器,就是判断用户有没有登录,没有登录就让他去登录
路由文件index.js
//vue项目的路由文件//导入vueimport Vue from 'vue'//导入路由import Router from 'vue-router'//导入路由对应的组件import Home from '@/pages/Home'import Student from "../pages/Student";import Teacher from "../pages/Teacher";import Team from "../pages/Team";import Course from "../pages/Course"import Login from "../pages/Login";import Test from "../pages/Test";import Chengji from "../pages/Chengji.vue"//在vue中挂载路由Vue.use(Router)export default new Router({ routes: [ { path: '/', name: 'Home', component: Home, redirect: '/student', children: [ { path:'/student', name: 'Student', component: Student }, { path: '/teacher', name: 'Teacher', component: Teacher }, { path: '/team', name: 'Team', component: Team }, { path: '/course', name: 'Course', component: Course }, {path: '/test',name: 'Test',component: Test} ] }, { path: '/login', name: 'Login', component: Login, } ]})
这里有个子路由的渲染
登录页面:
Login.vue:
<template> <div id="login"> <div class="backgroundImg"></div> <div class="container"> <div class="body"> <div class="title"> 学生信息管理系统 </div> <el-fORM :model="formData" status-icon :rules="rules" ref="ruleForm" label-width="50px" class="form"> <el-form-item label="账号" prop="username" class="form-item"> <el-input v-model="formData.username" placeholder="输入账号"></el-input> </el-form-item> <el-form-item label="密码" prop="passWord" class="form-item"> <el-input type="password" placeholder="输入密码" v-model="formData.password" autocomplete="off"></el-input> </el-form-item> <el-form-item class="login-bar"> <el-button type="success" @click="submitForm('ruleForm')">登录</el-button> <el-button type="danger" @click="resetForm('ruleForm')">重置</el-button> </el-form-item> </el-form> </div> </div> </div></template><script> export default { name: "Login", data() { var validateUsername = (rule, value, callback) => { if (value === '') { callback(new Error('请输入账号')); } else { callback(); } } var validatePassword = (rule, value, callback) => { if (value === '') { callback(new Error('请输入密码')); } else { callback(); } }; return { formData: { username: '', password: '', }, rules: { username: [ {validator: validateUsername, trigger: 'blur'} ], password: [ {validator: validatePassword, trigger: 'blur'} ], } }; }, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { this.axios({ method: 'post', url: '/api/login', data: { username: this.formData.username, password: this.formData.password, }, }).then((data) => { let ret = data.data; if (ret.success) { this.$message({ type: 'success', message: '登录成功', }); sessionStorage.setItem("auth", ret.data); this.$router.push("/") } else { this.$message({ message: ret.data, type: 'error', }); } }) } else { return false; } }); }, resetForm(formName) { this.$refs[formName].resetFields(); } } } </script>
主页效果图:
Home.vue
<template> <div id="home"> <LeftNav id="leftNav"></LeftNav> <TopNav id="topNav"></TopNav> <div class="container"> <transition name="el-fade-in-linear"> <router-view v-show="isRouterAlive" v-if="isRouterAlive"> </router-view> </transition> </div> </div> </template><script>import LeftNav from "../components/LeftNav"; import TopNav from "../components/TopNav"; export default { name: "Home", components: {TopNav, LeftNav}, // 提供方法到子组件中 provide() { return { reload: this.reload, } }, data() { return { isRouterAlive: true } }, methods: { // 刷新组件 reload() { this.isRouterAlive = false; this.$nextTick(function () { // 当数据被修改后使用这个方法会回调获取更新后的dom再渲染出来 this.isRouterAlive = true; }); } }, }</script>
侧边栏:Left.vue
<template> <div id="leftNav"> <div class="container"> <button v-for="item in navData" :to="{name: item.toUrl}" :class="curNav===item.value?'active':''" @click="navClick(item.value, item.toUrl)"> {{item.value}} </button> </div> </div></template><script> export default { name: "LeftNav", inject: ['reload'], methods: { // 点击导航栏后,先转化点击状态 navClick: function (curNav, toUrl) { this.reload(); this.curNav = curNav; this.$router.push(toUrl); }, setCurNav: function (newNav) { this.curNav = newNav; } }, data() { let navMap = { '/student': "学生管理", '/team': "班级管理", '/teacher': "教师管理", '/course': "课程管理", } return { navData: [ { value: '学生管理', toUrl: '/student', }, { value: '班级管理', toUrl: '/team' }, { value: '教师管理', toUrl: '/teacher' }, { value: '课程管理', toUrl: '/course' }, ], curNav: navMap[this.$route.path], } }, }</script>
Student.vue
<template> <div id="student"> <div class="titleBar"><span>学生管理</span></div> <div class="container"> <div class="body"> <div class="operationBar"> <el-button type="primary" @click="dialogVisible=true">添加学生</el-button> <el-dialog top="10vh" title="学生信息" :visible.sync="dialogVisible" :destroy-on-close="true" @opened="dialoGopen" @close="dialoGClose" width="40%"> <StudentDialog ref="dialog" :teams="this.teams" :teamId="this.currentTeamId" :initTeamLabel="this.initTeamLabel" :isCreate="this.isAddButton" :oldStudentData="{ ...this.oldStudentData }" > </StudentDialog> </el-dialog> <div class="selectBar"> <el-select @change="changeLabel" @clear="()=>{ let path = this.$router.history.current.path; this.$router.push(path); }" v-model="initTeamLabel" clearable placeholder="选择班级"> <el-option v-for="item in teams" :key="item.id" :label="getLabel(item)" :value="item.id"> </el-option> </el-select> </div> <div class="findBar"> <input v-model="findKey" type="text" placeholder="根据姓名查询" @keyup.enter="findLikeName"></input> <el-button type="primary" @click="findLikeName"><i class="el-icon-search"></i></el-button> <el-button type="primary" @click="()=>{this.findKey=null;findLikeName();}"><i class="el-icon-refresh-right"></i>重置 </el-button> </div> </div> <!--表格--> <el-table v-loading.lock="loading" :data="studentsData.content" border style="width: 96%; margin-left: 1vw; margin-top: 5vh;"> <el-table-column label=" #" width="50"> <template slot-scope="scope"> <span style="margin-left: 10px">{{ scope.$index + 1 }}</span> </template> </el-table-column> <el-table-column label="学号" width="100"> <!--通过 Scoped slot 可以获取到 row, column, $index 和 store(table 内部的状态管理)的数据--> <template slot-scope="scope"> <i class="el-icon-info"></i> <span style="margin-left: 10px">{{ scope.row.studentNumber }}</span> </template> </el-table-column> <el-table-column label="班级" width="200"> <template slot-scope="scope"> <span style="margin-left: 10px">{{ scope.row.teamFullName }}</span> </template> </el-table-column> <el-table-column label="姓名" width="100"> <template slot-scope="scope"> <div slot="reference" class="name-wrapper"> <el-tag size="medium" type="info">{{ scope.row.name }}</el-tag> </div> </template> </el-table-column> <el-table-column label="性别" show-overflow-tooltip width="50"> <template slot-scope="scope"> <span style="margin-left: 10px">{{getGender(scope.row.gender)}}</span> </template> </el-table-column> <el-table-column label="民族" width="90"> <template slot-scope="scope"> <span style="margin-left: 10px">{{scope.row.national}}</span> </template> </el-table-column> <el-table-column label="出生日期" width="120"> <template slot-scope="scope"> <span style="margin-left: 10px">{{ getDate(scope.row.birthDate) }}</span> </template> </el-table-column> <el-table-column label="籍贯" show-overflow-tooltip width="200"> <template slot-scope="scope"> <span style="margin-left: 10px">{{ scope.row.nativePlace }}</span> </template> </el-table-column> <el-table-column label="电话号码" width="130"> <template slot-scope="scope"> <el-tag type="info" effect="plain"> {{ scope.row.phoneNumber }} </el-tag> </template> </el-table-column> <el-table-column label="操作"> <template slot-scope="scope"> <el-button size="mini" @click="handleEdit(scope.row)">编辑 </el-button> <el-button size="mini" type="danger" @click="handleDelete(scope.row.id)">删除 </el-button> </template> </el-table-column> </el-table> <div class="pageBlock"> <el-pagination @current-change="handleCurrentChange" @size-change="handleSizeChange" :current-page="currentPageNumber" :page-sizes="[8,16,24,40]" :page-size="currentPageSize" layout="total,sizes, prev, pager, next" :total="this.studentsData.totalCount"> </el-pagination> </div> </div> <Footing class="footing"></Footing> </div> </div></template><script> import Footing from "../components/Footing"; import StudentPopover from "../components/StudentDialog"; import StudentDialog from "../components/StudentDialog"; import { Loading } from "element-ui"; export default { name: "Student", components: {StudentDialog, Footing}, inject: ['reload'], provide() { return { reload: this.reload, } }, methods: { // 对话框关闭时的回调函数 dialogClose: function() { // 默认为添加 this.isAddButton = true; }, // 对话框打开时,判断是添加还是更新 dialogOpen: function() { if (this.isAddButton) { return; } // 通过ref找到子组件对其直接控制 let dialog = this.$refs.dialog; dialog.studentData = dialog.oldStudentData; dialog.initTeamLabel = dialog.oldStudentData.teamFullName; }, handleEdit: function(row) { this.dialogVisible = true; this.isAddButton = false; this.oldStudentData = row; }, // 改变班级option changeLabel: function (value) { this.setTeamId(value); this.getStudentPageData(0, this.currentPageSize); }, // 设置url的query参数 setTeamId: function (newTeamId) { let path = this.$router.history.current.path; // 这里刷新了一次页面 this.$router.push({path, query: {teamId: newTeamId}}); this.currentTeamId = newTeamId; }, // 设置option的Label getLabel: function (team) { let year = this.getYear(team.schoolYear); return `${year}级${team.professional}专业${team.classNumber}` }, getYear: function (timestamp) { let date = new Date(timestamp); return date.getFullYear(); }, // 处理删除按钮 handleDelete: function (id) { this.axios({ method: 'delete', url: '/api/students/' + id, }).then((data) => { let ret = data.data; if (ret.success) { this.$message({ type: 'success', message: '删除成功', }); // 当前删除的是否是本页的最后一条数据 if (this.studentsData.content.length === 1 && this.currentPageNumber !== 1) { this.currentPageNumber--; this.getStudentPageData(this.currentPageNumber - 1, this.currentPageSize); } else { this.getStudentPageData(this.currentPageNumber - 1, this.currentPageSize); } } else { this.$message({ message: '删除失败', type: 'error', }); } }) }, // 处理分页改变 handleCurrentChange: function (val) { this.currentPageNumber = val; this.getStudentPageData(this.currentPageNumber - 1, this.currentPageSize); }, handleSizeChange: function(val) { // 设置新的页面大小后 this.currentPageSize = val; // 回到第一页 this.handleCurrentChange(1); }, // 根据名称查询 findLikeName: function () { this.handleCurrentChange(1); }, // 封装axios请求 getStudentPageData: function (number, size) { this.axios({ method: 'get', url: '/api/students', params: { pageNumber: number, pageSize: size, name: this.findKey, teamId: this.currentTeamId, } }).then((data) => { let ret = data.data; if (ret.success) { this.studentsData = ret.data; } else { this.$message({ message: '请求数据失败', type: 'error', }); } }); }, // 查询所有班级信息 getTeamAllData: function () { this.axios({ method: 'get', url: "/api/teams/all", }).then((data) => { let ret = data.data; if (ret.success) { this.teams = ret.data; // 如果初始化时url上有teamId if (this.currentTeamId != null) { let i; let len = ret.data.length; for (i = 0; i < len; i++) { if (ret.data[i].id == this.currentTeamId) { this.initTeamLabel = this.getLabel(ret.data[i]); break; } } if (i == len) { this.$message({ message: '不存在指定的班级', type: 'error', }); } } } else { this.$message({ message: '请求数据失败', type: 'error', }); } }) }, getGender: function (gender) { if (gender === null) { return ''; } if (gender) { return '男'; } else { return '女'; } }, getDate: function (timestamp) { let dateTime = new Date(timestamp); let year = dateTime.getFullYear(); let month = (dateTime.getMonth() + 1).toString().padStart(2, '0'); let day = dateTime.getDate().toString().padStart(2, '0'); return `${year}-${month}-${day}` } }, data() { // 刚进入页面时从url上获取teamId的初始值 let teamId = this.$route.query.teamId === undefined ? null : this.$route.query.teamId; return { // 姓名查询关键词 findKey: null, // 学生分页数据 studentsData: {}, // 当前页码 currentPageNumber: 1, // 当前页面数据数量 currentPageSize: 8, // 所有班级信息用于select teams: null, // 当前班级id,用于url上刷新 currentTeamId: teamId, // 如果url上有班级id,select上显示的是该班级的label initTeamLabel: null, // 对话框是否显示 dialogVisible: false, // 是否是添加按钮 isAddButton: true, // 旧学生数据 编辑使用 oldStudentData: null, // 是否显示加载 loading: false, } }, created() { this.loading = true; this.getStudentPageData(0, this.currentPageSize); this.getTeamAllData(); this.loading = false; } }</script>
studentDialog.vue
<template> <div id="studentDialog"> <div class="container"> <div class="properties"> <div class="property"> <span class="propertyTitle">学号:</span> <el-input class="propertyInput" v-model="studentData.studentNumber" placeholder="请输入学号"></el-input> </div> <div class="property"> <span class="propertyTitle">班级:</span> <el-select class="propertyInput" @change="labelChange" v-model="this.initTeamLabel" clearable placeholder="选择班级"> <el-option v-for="item in teams" :key="item.id" :label="getLabel(item)" :value="item.id"> </el-option> </el-select> </div> <div class="property"> <span class="propertyTitle">姓名:</span> <el-input class="propertyInput" v-model="studentData.name" placeholder="请输入姓名"></el-input> </div> <div class="property"> <span class="propertyTitle">性别:</span> <div class="propertyInput"> <el-radio-group v-model="studentData.gender"> <el-radio :label="true">男</el-radio> <el-radio :label="false">女</el-radio> </el-radio-group> </div> </div> <div class="property"> <span class="propertyTitle">民族:</span> <el-select class="propertyInput" v-model="studentData.national" clearable placeholder="选择民族"> <el-option v-for="item in nationals" :key="item" :value="item"> </el-option> </el-select> </div> <div class="property"> <span class="propertyTitle">出生日期:</span> <el-date-picker class="propertyInput" value-format="timestamp" v-model="studentData.birthDate" type="date" placeholder="选择出生日期"> </el-date-picker> </div> <div class="property"> <span class="propertyTitle">籍贯:</span> <el-input class="propertyInput" v-model="studentData.nativePlace" placeholder="请输入籍贯"></el-input> </div> <div class="property"> <span class="propertyTitle">电话号码:</span> <el-input class="propertyInput" maxlength="11" show-word-limit suffix-icon="el-icon-phone" v-model="studentData.phoneNumber" placeholder="请输入电话号码"></el-input> </div> <div slot="footer" class="dialog-footer"> <el-button @click="closeClick">取 消</el-button> <el-button type="primary" @click="solveClick">确 定</el-button> </div> </div> </div> </div></template><script> export default { name: "StudentDialog", props: ['teams', 'isCreate', 'oldStudentData', 'teamId', 'initTeamLabel'], inject: ['reload'], methods: { updateStudent: function() { this.axios({ method: 'put', url: '/api/students/' + this.studentData.id, data: this.studentData, }).then((data) => { let ret = data.data; if (ret.success) { this.$message({ type: 'success', message: '更新成功', }); // 刷新页面 this.reload(); } else { this.$message({ message: '更新失败' + ret.data, type: 'error', }); } }) }, createStudent: function() { this.axios({ method: 'post', url: '/api/students', data: this.studentData, }).then((data) => { let ret = data.data; if (ret.success) { this.$message({ type: 'success', message: '添加成功', }); // 刷新页面 this.reload(); } else { this.$message({ message: '添加失败' + ret.data, type: 'error', }); } }) }, // 班级下拉框改变时 labelChange: function(value) { this.initTeamLabel = value; this.studentData.teamId = value; }, // 确定按钮 solveClick: function() { if (this.isCreate) { this.createStudent(); } else { this.updateStudent(); } }, // 取消处理 closeClick: function() { // 关闭对话框 this.$parent.$parent.dialogVisible = false; }, // 设置option的Label getLabel: function (team) { let year = this.getYear(team.schoolYear); return `${year}级${team.professional}专业${team.classNumber}` }, getYear: function (timestamp) { let date = new Date(timestamp); return date.getFullYear(); }, setStudentData: function (data) { this.studentData = data; } }, data() { return { studentData: { teamId: this.teamId, }, nationals: [ "汉族", "壮族", "满族", "回族", "苗族", "维吾尔族", "土家族", "彝族", "蒙古族", "藏族", "布依族", "侗族", "瑶族", "朝鲜族", "白族", "哈尼族", "哈萨克族", "黎族", "傣族", "畲族", "傈僳族", "仡佬族", "东乡族", "高山族", "拉祜族", "水族", "佤族", "纳西族", "羌族", "土族", "仫佬族", "锡伯族", "柯尔克孜族", "达斡尔族", "景颇族", "毛南族", "撒拉族", "布朗族", "塔吉克族", "阿昌族", "普米族", "鄂温克族", "怒族", "京族", "基诺族", "德昂族", "保安族", "俄罗斯族", "裕固族", "乌孜别克族", "门巴族", "鄂伦春族", "独龙族", "塔塔尔族", "赫哲族", "珞巴族" ], } }, }</script><style scoped> .container { display: flex; justify-content: center; } .properties { width: 100%; display: flex; flex-direction: column; } .property { width: 80%; display: flex; justify-content: space-between; padding-bottom: 1vh; } .propertyTitle { font-weight: 600; width: 40%; display: flex; justify-content: flex-end; align-items: center; padding-right: 1vw; } .propertyTitle:before { content: "*"; color: rgba(241,8,8,0.88); padding-right: 2px; } .propertyInput { height: 40px; width: 60%; display: flex; align-items: center; } .dialog-footer { display: flex; justify-content: flex-end; padding-right: 20%; padding-top: 1vh; }</style>
来源地址:https://blog.csdn.net/ziyue13/article/details/130087077
--结束END--
本文标题: 基于Springboot+vue+elementUI+MySQL的学生信息管理系统(一)前端部分
本文链接: https://www.lsjlt.com/news/423377.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-05-03
2024-05-03
2024-05-03
2024-05-03
2024-05-03
2024-05-03
2024-05-03
2024-05-03
2024-05-03
2024-05-03
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0