源码在本人博客资源当中,本文为项目代码详细介绍解释,供于大家学习使用

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/&gt;'
})

这里唯一的难点就是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&gt;
  <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, $indexstoretable 内部状态管理)的数据-->
            <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);
      },
      // 设置urlquery参数
      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 &amp;&amp; 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_34918.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除!

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注