源码在本人博客资源当中,本文为项目代码的详细介绍解释,供于大家学习使用
Vue项目的入口文件:mian.js
//vue项目入口文件
//导入vue
import Vue from 'vue'
//导入根组件app
import App from './App'
//导入路由文件
import router from './router'
//导入ElementUI
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
//导入axios
import axios from "axios";
import VueAxios from "vue-axios";
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
// use
Vue.use(mavonEditor)
//在vue当中挂载elementUI和axios
Vue.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对象
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
这里唯一的难点就是axios请求拦截器和响应拦截器,就是判断用户有没有登录,没有登录就让他去登录
路由文件index.js
//vue项目的路由文件
//导入vue
import 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">
/* 这段代码使用了 Element UI 框架的 <el-form> 组件,用于生成表单。其中,:model="formData" 表示组件中的数据与 formData 变量进行了双向绑定, :rules="rules" 表示对表单进行验证的规则,这可以保证表单填写的合法性。status-icon 属性表示在输入框内增加状态图标,:label-width="50px" 表示表单项左侧的标题部分宽度为 50 像素,class="form" 表示使用指定的样式类名来设置表单的样式。
ref="ruleForm" 配合 this.$refs.ruleForm.validate() 方法可以触发表单验证。当需要在组件内使用整个表单数据时,我们可以通过 this.formData 进行访问。总之,通过使用 <el-form> ,我们可以方便地生成表单,并进行数据绑定、验证等操作。*/
<el-form-item label="账号" prop="username" class="form-item">
<el-input v-model="formData.username" placeholder="输入账号"></el-input>
</el-form-item>
/*这段代码是使用 Element UI 框架的 <el-form-item> 组件来生成一个表单项。其中,label="账号" 表示表单项左侧的标题为“账号”。 prop="username" 表示该表单项的唯一标识为 username,在表单验证时可以使用该标识进行验证。 class="form-item" 表示使用指定的样式类名来设置该表单项的样式。
这个表单项的主要内容位于 <el-input> 中,使用了 v-model="formData.username" 将用户输入的值与 formData 对应的 username 属性进行双向绑定。 placeholder="输入账号" 表示在该输入框未填写前,会显示提示信息“输入账号”。
总之,通过使用 <el-form-item> ,我们可以方便地生成表单项,并设置其样式和验证规则;通过使用 <el-input> ,我们可以生成文本输入框,并将其与组件中的数据进行双向绑定。*/
<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();
}
}
/*这段代码定义了一个验证函数 validateUsername ,用于对表单项的“账号”进行验证。该函数接受三个参数: rule 表示验证规则对象,value 表示当前表单项输入的值,callback 表示回调函数。
在 validateUsername 函数中,首先判断用户输入的值是否为空。如果为空,则通过调用 callback(new Error('请输入账号')) 抛出一个错误信息。如果不为空,则通过调用 callback() 这个方法通知表单验证通过。
这个函数体现了 Element UI 中表单验证的基本思想:将验证规则和验证逻辑分开,并且将验证结果通过回调函数返回给组件。由于这个函数是针对“账号”表单项的验证,所以我们可以在 <el-form-item> 中的 rules 属性中指定该验证函数,从而对该表单项进行验证。
总之,通过将表单项的验证逻辑封装为一个函数,我们可以方便地在 Element UI 中对表单进行自定义的验证规则。*/
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'}
],
}
/*这段代码是用来设置 <el-form> 组件中表单项的验证规则。在这里, rules 属性值是一个对象,其中每个属性名(如 username 和 password)对应着一个表单项的 prop 值,也就是该表单项的唯一标识符。而其属性值则是一个数组,表示一个数组中可以包含多个验证规则,每个规则都是一个对象。
在这个对象中, validator 表示要使用的验证方法,这里使用了之前定义的 validateUsername 和 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;
}
});
},
/*这段代码是一个表单提交函数,用于在用户点击“登录”按钮时提交表单数据,并向服务器发送请求验证用户身份。
首先,通过 this.$refs[formName].validate() 方法对表单进行验证。该方法接受一个回调函数作为参数,当表单验证通过时可执行回调函数中的代码,否则返回一个错误。这里使用了 ES6 中的箭头函数,使得代码更加简洁。
当表单验证通过之后,会向服务器发送一个 POST 请求,请求的地址为 /api/login 。其中,传递给服务器的数据包括用户输入的账号和密码,这些数据存储在组件中的 formData 对象中。在服务器处理完请求之后,返回的结果保存在 data 变量中,使用 ret 变量来接收服务器的响应数据。如果服务器返回的数据中 success 属性值为 true,说明用户已经成功登录,此时弹出一个提示框,提示用户登录成功,并将用户的身份信息写入 sessionStorage 中。最后,使用 this.$router.push("/") 方法将用户重定向到系统首页。
如果服务器返回的数据中 success 属性值为 false,说明用户登录失败,此时弹出一个带有错误提示信息的提示框,提醒用户重新输入账号和密码。*/
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}
/* 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>
/*
这段代码是一个 Vue.js 组件中的模板,用于渲染多个 button 元素,每个 button 元素代表着导航栏中的一个导航链接。navData 可能是一个数组,包含了每个导航按钮的名称和跳转路径等信息。通过 v-for 指令,可以将 navData 数组中的每个元素都映射成一个 button 元素,并依次进行渲染。
其中,:to="{name: item.toUrl}" 是一个 Vue Router 的路由跳转,在这里指定了该按钮的目标路由地址。:class="curNav===item.value?'active':''" 用于动态绑定该按钮的 class 属性,当选中该按钮时,会动态添加 active 样式类,以高亮显示该按钮。同时,@click 事件监听器将触发 navClick 方法,并传递两个参数:该按钮对应的 value 值和该按钮对应的跳转路径 toUrl,以便在组件中处理点击该按钮后的相应逻辑。
需要注意的是,在渲染该页面时,应该保证 navData 数组中的每个元素都有一个唯一的 value 值,以便在组件中进行状态管理和路由跳转等操作。
*/
</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%">
/*
这段代码是使用了Element UI框架的 <el-dialog> 组件进行弹窗显示。
其中,top="10vh" 表示弹窗距离顶部的距离为 10vh。
title="学生信息" 表示弹窗的标题为 “学生信息”。 :visible.sync="dialogVisible" 表示控制弹窗是否可见的变量为 dialogVisible。
当dialogVisible的值被改变时,弹窗的可见性也会同步变化。 :destroy-on-close="true" 表示当弹窗被关闭时,将该组件销毁而不是保留在DOM中。 @opened="dialogOpen" 表示组件在打开时触发回调函数 dialogOpen。 @close="dialogClose" 表示组件在关闭时触发回调函数 dialogClose。width="40%" 表示弹窗宽度为父元素宽度的 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>
/*@change="changeLabel" 指定了当用户选择班级信息后触发的函数 changeLabel,该函数可以在 Vue 实例中定义,用于处理选择班级后的相应逻辑。
@clear="..." 则指定了清空选择框后触发的函数,这里的函数中使用了 this.$router.history.current.path 获取当前路由路径,并通过 $router.push 方法重新跳转到当前路由,以清空已选中的班级信息。
v-model="initTeamLabel" 是双向绑定指令,用于将选中的班级信息绑定到 Vue 实例的 initTeamLabel 变量中,以在组件外部进行访问和处理。
<el-option> 标签用于渲染下拉列表中的每个选项,通过 v-for 指令遍历 teams 数组中的每个元素 item,并将其渲染为一个选项,并为该选项绑定 id 属性作为唯一标识符,同时为该选项绑定 label 和 value 属性,分别代表选项的显示名称和实际值。*/
<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;">
/*
其中 v-loading.lock="loading" 指定了在加载数据时显示一个遮罩层,并禁止用户进行操作。loading 是一个布尔类型变量,用于指示当前是否正在加载数据,可以在 Vue 实例中进行定义和处理。
:data="studentsData.content" 绑定了表格的数据源 studentsData.content,该数据源通常是一个数组类型,在 Vue 实例中定义,在表格中可以通过 v-for 指令循环渲染每一行数据。
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>