离校前端框架,包括数据字典、工作队伍、新闻公告模块
diff --git a/leave-school-vue/src/views/404.vue b/leave-school-vue/src/views/404.vue
new file mode 100644
index 0000000..733e038
--- /dev/null
+++ b/leave-school-vue/src/views/404.vue
@@ -0,0 +1,236 @@
+<template>
+  <div class="wscn-http404-container">
+    <div class="wscn-http404">
+      <div class="pic-404">
+        <img class="pic-404__parent" :src="img_404" alt="404">
+        <img class="pic-404__child left" :src="img_404_cloud" alt="404">
+        <img class="pic-404__child mid" :src="img_404_cloud" alt="404">
+        <img class="pic-404__child right" :src="img_404_cloud" alt="404">
+      </div>
+      <div class="bullshit">
+        <div class="bullshit__oops">OOPS!</div>
+        <div class="bullshit__info">
+          <a class='link-type' href='' target='_blank'></a>
+        </div>
+        <div class="bullshit__headline">{{ message }}</div>
+        <div class="bullshit__info">请检查您输入的网址是否正确,请点击以下按钮返回主页或者发送错误报告</div>
+        <a href="" class="bullshit__return-home">返回首页</a>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import img_404 from '@/assets/404_images/404.png'
+import img_404_cloud from '@/assets/404_images/404_cloud.png'
+
+export default {
+  name: 'page404',
+  data() {
+    return {
+      img_404,
+      img_404_cloud
+    }
+  },
+  computed: {
+    message() {
+      return '页面找不到了......'
+    }
+  }
+}
+</script>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+.wscn-http404-container{
+  transform: translate(-50%,-50%);
+  position: absolute;
+  top: 40%;
+  left: 50%;
+}
+.wscn-http404 {
+  position: relative;
+  width: 1200px;
+  padding: 0 50px;
+  overflow: hidden;
+  .pic-404 {
+    position: relative;
+    float: left;
+    width: 600px;
+    overflow: hidden;
+    &__parent {
+      width: 100%;
+    }
+    &__child {
+      position: absolute;
+      &.left {
+        width: 80px;
+        top: 17px;
+        left: 220px;
+        opacity: 0;
+        animation-name: cloudLeft;
+        animation-duration: 2s;
+        animation-timing-function: linear;
+        animation-fill-mode: forwards;
+        animation-delay: 1s;
+      }
+      &.mid {
+        width: 46px;
+        top: 10px;
+        left: 420px;
+        opacity: 0;
+        animation-name: cloudMid;
+        animation-duration: 2s;
+        animation-timing-function: linear;
+        animation-fill-mode: forwards;
+        animation-delay: 1.2s;
+      }
+      &.right {
+        width: 62px;
+        top: 100px;
+        left: 500px;
+        opacity: 0;
+        animation-name: cloudRight;
+        animation-duration: 2s;
+        animation-timing-function: linear;
+        animation-fill-mode: forwards;
+        animation-delay: 1s;
+      }
+      @keyframes cloudLeft {
+        0% {
+          top: 17px;
+          left: 220px;
+          opacity: 0;
+        }
+        20% {
+          top: 33px;
+          left: 188px;
+          opacity: 1;
+        }
+        80% {
+          top: 81px;
+          left: 92px;
+          opacity: 1;
+        }
+        100% {
+          top: 97px;
+          left: 60px;
+          opacity: 0;
+        }
+      }
+      @keyframes cloudMid {
+        0% {
+          top: 10px;
+          left: 420px;
+          opacity: 0;
+        }
+        20% {
+          top: 40px;
+          left: 360px;
+          opacity: 1;
+        }
+        70% {
+          top: 130px;
+          left: 180px;
+          opacity: 1;
+        }
+        100% {
+          top: 160px;
+          left: 120px;
+          opacity: 0;
+        }
+      }
+      @keyframes cloudRight {
+        0% {
+          top: 100px;
+          left: 500px;
+          opacity: 0;
+        }
+        20% {
+          top: 120px;
+          left: 460px;
+          opacity: 1;
+        }
+        80% {
+          top: 180px;
+          left: 340px;
+          opacity: 1;
+        }
+        100% {
+          top: 200px;
+          left: 300px;
+          opacity: 0;
+        }
+      }
+    }
+  }
+  .bullshit {
+    position: relative;
+    float: left;
+    width: 300px;
+    padding: 30px 0;
+    overflow: hidden;
+    &__oops {
+      font-size: 32px;
+      font-weight: bold;
+      line-height: 40px;
+      color: #1482f0;
+      opacity: 0;
+      margin-bottom: 20px;
+      animation-name: slideUp;
+      animation-duration: 0.5s;
+      animation-fill-mode: forwards;
+    }
+    &__headline {
+      font-size: 20px;
+      line-height: 24px;
+      color: #222;
+      font-weight: bold;
+      opacity: 0;
+      margin-bottom: 10px;
+      animation-name: slideUp;
+      animation-duration: 0.5s;
+      animation-delay: 0.1s;
+      animation-fill-mode: forwards;
+    }
+    &__info {
+      font-size: 13px;
+      line-height: 21px;
+      color: grey;
+      opacity: 0;
+      margin-bottom: 30px;
+      animation-name: slideUp;
+      animation-duration: 0.5s;
+      animation-delay: 0.2s;
+      animation-fill-mode: forwards;
+    }
+    &__return-home {
+      display: block;
+      float: left;
+      width: 110px;
+      height: 36px;
+      background: #1482f0;
+      border-radius: 100px;
+      text-align: center;
+      color: #ffffff;
+      opacity: 0;
+      font-size: 14px;
+      line-height: 36px;
+      cursor: pointer;
+      animation-name: slideUp;
+      animation-duration: 0.5s;
+      animation-delay: 0.3s;
+      animation-fill-mode: forwards;
+    }
+    @keyframes slideUp {
+      0% {
+        transform: translateY(60px);
+        opacity: 0;
+      }
+      100% {
+        transform: translateY(0);
+        opacity: 1;
+      }
+    }
+  }
+}
+</style>
diff --git a/leave-school-vue/src/views/dashboard/index.vue b/leave-school-vue/src/views/dashboard/index.vue
new file mode 100644
index 0000000..4b4625c
--- /dev/null
+++ b/leave-school-vue/src/views/dashboard/index.vue
@@ -0,0 +1,32 @@
+<template>
+  <div class="dashboard-container">
+    <div class="dashboard-text">name:{{name}}</div>
+    <div class="dashboard-text">roles:<span v-for='role in roles' :key='role'>{{role}}</span></div>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+
+export default {
+  name: 'dashboard',
+  computed: {
+    ...mapGetters([
+      'name',
+      'roles'
+    ])
+  }
+}
+</script>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+.dashboard {
+  &-container {
+    margin: 30px;
+  }
+  &-text {
+    font-size: 30px;
+    line-height: 46px;
+  }
+}
+</style>
diff --git a/leave-school-vue/src/views/layout/Layout.vue b/leave-school-vue/src/views/layout/Layout.vue
new file mode 100644
index 0000000..df7af87
--- /dev/null
+++ b/leave-school-vue/src/views/layout/Layout.vue
@@ -0,0 +1,74 @@
+<template>
+  <div class="app-wrapper" :class="classObj">
+    <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"></div>
+    <sidebar class="sidebar-container"></sidebar>
+    <div class="main-container">
+      <navbar></navbar>
+      <tags-view v-if='showtags'></tags-view>
+      <app-main></app-main>
+    </div>
+  </div>
+</template>
+
+<script>
+import { Navbar, Sidebar, AppMain, TagsView } from './components'
+import ResizeMixin from './mixin/ResizeHandler'
+
+export default {
+  name: 'layout',
+  components: {
+    Navbar,
+    Sidebar,
+    AppMain,
+    TagsView
+  },
+  mixins: [ResizeMixin],
+  computed: {
+    showtags() {
+      return process.env.SHOW_TAGS
+    },
+    sidebar() {
+      return this.$store.state.app.sidebar
+    },
+    device() {
+      return this.$store.state.app.device
+    },
+    classObj() {
+      return {
+        hideSidebar: !this.sidebar.opened,
+        openSidebar: this.sidebar.opened,
+        withoutAnimation: this.sidebar.withoutAnimation,
+        mobile: this.device === 'mobile'
+      }
+    }
+  },
+  methods: {
+    handleClickOutside() {
+      this.$store.dispatch('CloseSideBar', { withoutAnimation: false })
+    }
+  }
+}
+</script>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+  @import "src/styles/mixin.scss";
+  .app-wrapper {
+    @include clearfix;
+    position: relative;
+    height: 100%;
+    width: 100%;
+    &.mobile.openSidebar{
+      position: fixed;
+      top: 0;
+    }
+  }
+  .drawer-bg {
+    background: #000;
+    opacity: 0.3;
+    width: 100%;
+    top: 0;
+    height: 100%;
+    position: absolute;
+    z-index: 999;
+  }
+</style>
diff --git a/leave-school-vue/src/views/layout/components/AppMain.vue b/leave-school-vue/src/views/layout/components/AppMain.vue
new file mode 100644
index 0000000..64ecff8
--- /dev/null
+++ b/leave-school-vue/src/views/layout/components/AppMain.vue
@@ -0,0 +1,33 @@
+<template>
+  <section class="app-main">
+    <transition name="fade" mode="out-in">
+      <!-- <router-view :key="key"></router-view> -->
+      <keep-alive :include="cachedViews">
+        <router-view :key="key"></router-view>
+      </keep-alive>
+    </transition>
+  </section>
+</template>
+
+<script>
+export default {
+  name: 'AppMain',
+  computed: {
+    cachedViews() {
+      return this.$store.state.tagsView.cachedViews
+    },
+    key() {
+      return this.$route.fullPath
+    }
+  }
+}
+</script>
+
+<style scoped>
+.app-main {
+  /*50 = navbar  */
+  min-height: calc(100vh - 84px);
+  position: relative;
+  overflow: hidden;
+}
+</style>
diff --git a/leave-school-vue/src/views/layout/components/Navbar.vue b/leave-school-vue/src/views/layout/components/Navbar.vue
new file mode 100644
index 0000000..c901e8f
--- /dev/null
+++ b/leave-school-vue/src/views/layout/components/Navbar.vue
@@ -0,0 +1,95 @@
+<template>
+  <el-menu class="navbar" mode="horizontal">
+    <hamburger class="hamburger-container" :toggleClick="toggleSideBar" :isActive="sidebar.opened"></hamburger>
+    <breadcrumb></breadcrumb>
+    <el-dropdown class="avatar-container" trigger="click">
+      <div class="avatar-wrapper">
+        <img class="user-avatar" :src="avatar">
+        <i class="el-icon-caret-bottom"></i>
+      </div>
+      <el-dropdown-menu class="user-dropdown" slot="dropdown">
+        <router-link class="inlineBlock" to="/">
+          <el-dropdown-item>
+            首页
+          </el-dropdown-item>
+        </router-link>
+        <el-dropdown-item divided>
+          <span @click="logout" style="display:block;">注销</span>
+        </el-dropdown-item>
+      </el-dropdown-menu>
+    </el-dropdown>
+  </el-menu>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import Breadcrumb from '@/components/Breadcrumb'
+import Hamburger from '@/components/Hamburger'
+
+export default {
+  components: {
+    Breadcrumb,
+    Hamburger
+  },
+  computed: {
+    ...mapGetters([
+      'sidebar',
+      'avatar'
+    ])
+  },
+  methods: {
+    toggleSideBar() {
+      this.$store.dispatch('ToggleSideBar')
+    },
+    logout() {
+      var pro = this.$store.dispatch('LogOut')
+      pro.then(() => {
+        location.reload() // 为了重新实例化vue-router对象 避免bug
+      })
+    }
+  }
+}
+</script>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+.navbar {
+  height: 50px;
+  line-height: 50px;
+  border-radius: 0px !important;
+  .hamburger-container {
+    line-height: 58px;
+    height: 50px;
+    float: left;
+    padding: 0 10px;
+  }
+  .screenfull {
+    position: absolute;
+    right: 90px;
+    top: 16px;
+    color: red;
+  }
+  .avatar-container {
+    height: 50px;
+    display: inline-block;
+    position: absolute;
+    right: 35px;
+    .avatar-wrapper {
+      cursor: pointer;
+      margin-top: 5px;
+      position: relative;
+      .user-avatar {
+        width: 40px;
+        height: 40px;
+        border-radius: 10px;
+      }
+      .el-icon-caret-bottom {
+        position: absolute;
+        right: -20px;
+        top: 25px;
+        font-size: 12px;
+      }
+    }
+  }
+}
+</style>
+
diff --git a/leave-school-vue/src/views/layout/components/Sidebar/SidebarItem.vue b/leave-school-vue/src/views/layout/components/Sidebar/SidebarItem.vue
new file mode 100644
index 0000000..78edb91
--- /dev/null
+++ b/leave-school-vue/src/views/layout/components/Sidebar/SidebarItem.vue
@@ -0,0 +1,78 @@
+<template>
+  <div v-if="!item.hidden&&item.children" class="menu-wrapper">
+
+      <router-link v-if="hasOneShowingChild(item.children) && !onlyOneChild.children&&!item.alwaysShow" :to="resolvePath(onlyOneChild.path)">
+        <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
+          <svg-icon v-if="onlyOneChild.meta&&onlyOneChild.meta.icon" :icon-class="onlyOneChild.meta.icon"></svg-icon>
+          <span v-if="onlyOneChild.meta&&onlyOneChild.meta.title" slot="title">{{onlyOneChild.meta.title}}</span>
+        </el-menu-item>
+      </router-link>
+
+      <el-submenu v-else :index="item.name||item.path">
+        <template slot="title">
+          <svg-icon v-if="item.meta&&item.meta.icon" :icon-class="item.meta.icon"></svg-icon>
+          <span v-if="item.meta&&item.meta.title" slot="title">{{item.meta.title}}</span>
+        </template>
+
+        <template v-for="child in item.children" v-if="!child.hidden">
+          <sidebar-item :is-nest="true" class="nest-menu" v-if="child.children&&child.children.length>0" :item="child" :key="child.path" :base-path="resolvePath(child.path)"></sidebar-item>
+
+          <router-link v-else :to="resolvePath(child.path)" :key="child.name">
+            <el-menu-item :index="resolvePath(child.path)">
+              <svg-icon v-if="child.meta&&child.meta.icon" :icon-class="child.meta.icon"></svg-icon>
+              <span v-if="child.meta&&child.meta.title" slot="title">{{child.meta.title}}</span>
+            </el-menu-item>
+          </router-link>
+        </template>
+      </el-submenu>
+
+  </div>
+</template>
+
+<script>
+import path from 'path'
+
+export default {
+  name: 'SidebarItem',
+  props: {
+    // route配置json
+    item: {
+      type: Object,
+      required: true
+    },
+    isNest: {
+      type: Boolean,
+      default: false
+    },
+    basePath: {
+      type: String,
+      default: ''
+    }
+  },
+  data() {
+    return {
+      onlyOneChild: null
+    }
+  },
+  methods: {
+    hasOneShowingChild(children) {
+      const showingChildren = children.filter(item => {
+        if (item.hidden) {
+          return false
+        } else {
+          // temp set(will be used if only has one showing child )
+          this.onlyOneChild = item
+          return true
+        }
+      })
+      if (showingChildren.length === 1) {
+        return true
+      }
+      return false
+    },
+    resolvePath(...paths) {
+      return path.resolve(this.basePath, ...paths)
+    }
+  }
+}
+</script>
diff --git a/leave-school-vue/src/views/layout/components/Sidebar/index.vue b/leave-school-vue/src/views/layout/components/Sidebar/index.vue
new file mode 100644
index 0000000..a84207e
--- /dev/null
+++ b/leave-school-vue/src/views/layout/components/Sidebar/index.vue
@@ -0,0 +1,35 @@
+<template>
+  <el-scrollbar wrapClass="scrollbar-wrapper">
+    <el-menu
+      mode="vertical"
+      :show-timeout="200"
+      :default-active="$route.path"
+      :collapse="isCollapse"
+      background-color="#304156"
+      text-color="#bfcbd9"
+      active-text-color="#409EFF"
+    >
+      <sidebar-item v-for="route in routes" :key="route.name" :item="route" :base-path="route.path"></sidebar-item>
+    </el-menu>
+  </el-scrollbar>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import SidebarItem from './SidebarItem'
+
+export default {
+  components: { SidebarItem },
+  computed: {
+    ...mapGetters([
+      'sidebar'
+    ]),
+    routes() {
+      return this.$router.options.routes
+    },
+    isCollapse() {
+      return !this.sidebar.opened
+    }
+  }
+}
+</script>
diff --git a/leave-school-vue/src/views/layout/components/TagsView.vue b/leave-school-vue/src/views/layout/components/TagsView.vue
new file mode 100644
index 0000000..121c2b2
--- /dev/null
+++ b/leave-school-vue/src/views/layout/components/TagsView.vue
@@ -0,0 +1,205 @@
+<template>
+  <div class="tags-view-container">
+    <scroll-pane class='tags-view-wrapper' ref='scrollPane'>
+      <router-link ref='tag' class="tags-view-item" :class="isActive(tag)?'active':''" v-for="tag in Array.from(visitedViews)"
+        :to="tag" :key="tag.path" @contextmenu.prevent.native="openMenu(tag,$event)">
+        {{tag.title}}
+        <span class='el-icon-close' @click.prevent.stop='closeSelectedTag(tag)'></span>
+      </router-link>
+    </scroll-pane>
+    <ul class='contextmenu' v-show="visible" :style="{left:left+'px',top:top+'px'}">
+      <li @click="closeSelectedTag(selectedTag)">关闭当前</li>
+      <li @click="closeOthersTags">关闭其它</li>
+      <li @click="closeAllTags">关闭所有</li>
+    </ul>
+  </div>
+</template>
+
+<script>
+import ScrollPane from '@/components/ScrollPane'
+// import { generateTitle } from '@/utils/i18n'
+
+export default {
+  components: { ScrollPane },
+  data() {
+    return {
+      visible: false,
+      top: 0,
+      left: 0,
+      selectedTag: {}
+    }
+  },
+  computed: {
+    visitedViews() {
+      return this.$store.state.tagsView.visitedViews
+    }
+  },
+  watch: {
+    $route() {
+      this.addViewTags()
+      this.moveToCurrentTag()
+    },
+    visible(value) {
+      if (value) {
+        document.body.addEventListener('click', this.closeMenu)
+      } else {
+        document.body.removeEventListener('click', this.closeMenu)
+      }
+    }
+  },
+  mounted() {
+    this.addViewTags()
+  },
+  methods: {
+    // generateTitle, // generateTitle by vue-i18n
+    generateRoute() {
+      if (this.$route.name) {
+        return this.$route
+      }
+      return false
+    },
+    isActive(route) {
+      return route.path === this.$route.path
+    },
+    addViewTags() {
+      const route = this.generateRoute()
+      if (!route) {
+        return false
+      }
+      this.$store.dispatch('addVisitedViews', route)
+    },
+    moveToCurrentTag() {
+      const tags = this.$refs.tag
+      this.$nextTick(() => {
+        for (const tag of tags) {
+          if (tag.to.path === this.$route.path) {
+            this.$refs.scrollPane.moveToTarget(tag.$el)
+            break
+          }
+        }
+      })
+    },
+    closeSelectedTag(view) {
+      this.$store.dispatch('delVisitedViews', view).then((views) => {
+        if (this.isActive(view)) {
+          const latestView = views.slice(-1)[0]
+          if (latestView) {
+            this.$router.push(latestView)
+          } else {
+            this.$router.push('/')
+          }
+        }
+      })
+    },
+    closeOthersTags() {
+      this.$router.push(this.selectedTag)
+      this.$store.dispatch('delOthersViews', this.selectedTag).then(() => {
+        this.moveToCurrentTag()
+      })
+    },
+    closeAllTags() {
+      this.$store.dispatch('delAllViews')
+      this.$router.push('/')
+    },
+    openMenu(tag, e) {
+      this.visible = true
+      this.selectedTag = tag
+      const offsetLeft = this.$el.getBoundingClientRect().left // container margin left
+      this.left = e.clientX - offsetLeft + 15 // 15: margin right
+      this.top = e.clientY
+    },
+    closeMenu() {
+      this.visible = false
+    }
+  }
+}
+</script>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+.tags-view-container {
+  .tags-view-wrapper {
+    background: #fff;
+    height: 34px;
+    border-bottom: 1px solid #d8dce5;
+    box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
+    .tags-view-item {
+      display: inline-block;
+      position: relative;
+      height: 26px;
+      line-height: 26px;
+      border: 1px solid #d8dce5;
+      color: #495060;
+      background: #fff;
+      padding: 0 8px;
+      font-size: 12px;
+      margin-left: 5px;
+      margin-top: 4px;
+      &:first-of-type {
+        margin-left: 15px;
+      }
+      &.active {
+        background-color: #42b983;
+        color: #fff;
+        border-color: #42b983;
+        &::before {
+          content: '';
+          background: #fff;
+          display: inline-block;
+          width: 8px;
+          height: 8px;
+          border-radius: 50%;
+          position: relative;
+          margin-right: 2px;
+        }
+      }
+    }
+  }
+  .contextmenu {
+    margin: 0;
+    background: #fff;
+    z-index: 100;
+    position: absolute;
+    list-style-type: none;
+    padding: 5px 0;
+    border-radius: 4px;
+    font-size: 12px;
+    font-weight: 400;
+    color: #333;
+    box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);
+    li {
+      margin: 0;
+      padding: 7px 16px;
+      cursor: pointer;
+      &:hover {
+        background: #eee;
+      }
+    }
+  }
+}
+</style>
+
+<style rel="stylesheet/scss" lang="scss">
+//reset element css of el-icon-close
+.tags-view-wrapper {
+  .tags-view-item {
+    .el-icon-close {
+      width: 16px;
+      height: 16px;
+      vertical-align: 2px;
+      border-radius: 50%;
+      text-align: center;
+      transition: all .3s cubic-bezier(.645, .045, .355, 1);
+      transform-origin: 100% 50%;
+      &:before {
+        transform: scale(.6);
+        display: inline-block;
+        vertical-align: -3px;
+      }
+      &:hover {
+        background-color: #b4bccc;
+        color: #fff;
+      }
+    }
+  }
+}
+</style>
diff --git a/leave-school-vue/src/views/layout/components/index.js b/leave-school-vue/src/views/layout/components/index.js
new file mode 100644
index 0000000..7cddb7c
--- /dev/null
+++ b/leave-school-vue/src/views/layout/components/index.js
@@ -0,0 +1,4 @@
+export { default as Navbar } from './Navbar'
+export { default as Sidebar } from './Sidebar'
+export { default as TagsView } from './TagsView'
+export { default as AppMain } from './AppMain'
diff --git a/leave-school-vue/src/views/layout/mixin/ResizeHandler.js b/leave-school-vue/src/views/layout/mixin/ResizeHandler.js
new file mode 100644
index 0000000..b22c8bb
--- /dev/null
+++ b/leave-school-vue/src/views/layout/mixin/ResizeHandler.js
@@ -0,0 +1,41 @@
+import store from '@/store'
+
+const { body } = document
+const WIDTH = 1024
+const RATIO = 3
+
+export default {
+  watch: {
+    $route(route) {
+      if (this.device === 'mobile' && this.sidebar.opened) {
+        store.dispatch('CloseSideBar', { withoutAnimation: false })
+      }
+    }
+  },
+  beforeMount() {
+    window.addEventListener('resize', this.resizeHandler)
+  },
+  mounted() {
+    const isMobile = this.isMobile()
+    if (isMobile) {
+      store.dispatch('ToggleDevice', 'mobile')
+      store.dispatch('CloseSideBar', { withoutAnimation: true })
+    }
+  },
+  methods: {
+    isMobile() {
+      const rect = body.getBoundingClientRect()
+      return rect.width - RATIO < WIDTH
+    },
+    resizeHandler() {
+      if (!document.hidden) {
+        const isMobile = this.isMobile()
+        store.dispatch('ToggleDevice', isMobile ? 'mobile' : 'desktop')
+
+        if (isMobile) {
+          store.dispatch('CloseSideBar', { withoutAnimation: true })
+        }
+      }
+    }
+  }
+}
diff --git a/leave-school-vue/src/views/login/index.vue b/leave-school-vue/src/views/login/index.vue
new file mode 100644
index 0000000..fd4a9c1
--- /dev/null
+++ b/leave-school-vue/src/views/login/index.vue
@@ -0,0 +1,168 @@
+<template>
+  <div class="login-container">
+    <el-form class="login-form" autoComplete="on" :model="loginForm" :rules="loginRules" ref="loginForm" label-position="left">
+      <h3 class="title">离校管理系统</h3>
+      <el-form-item prop="username">
+        <span class="svg-container svg-container_login">
+          <svg-icon icon-class="user" />
+        </span>
+        <el-input name="username" type="text" v-model="loginForm.username" autoComplete="on" placeholder="username" />
+      </el-form-item>
+      <el-form-item prop="password">
+        <span class="svg-container">
+          <svg-icon icon-class="password"></svg-icon>
+        </span>
+        <el-input name="password" :type="pwdType" @keyup.enter.native="handleLogin" v-model="loginForm.password" autoComplete="on"
+          placeholder="password"></el-input>
+          <span class="show-pwd" @click="showPwd"><svg-icon icon-class="eye" /></span>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" style="width:100%;" :loading="loading" @click.native.prevent="handleLogin">
+          登录
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import { isvalidUsername } from '@/utils/validate'
+
+export default {
+  name: 'login',
+  data() {
+    const validateUsername = (rule, value, callback) => {
+      if (!isvalidUsername(value)) {
+        callback(new Error('请输入正确的用户名'))
+      } else {
+        callback()
+      }
+    }
+    const validatePass = (rule, value, callback) => {
+      if (value.length < 5) {
+        callback(new Error('密码不能小于5位'))
+      } else {
+        callback()
+      }
+    }
+    return {
+      loginForm: {
+        username: 'admin',
+        password: 'admin'
+      },
+      loginRules: {
+        username: [{ required: true, trigger: 'blur', validator: validateUsername }],
+        password: [{ required: true, trigger: 'blur', validator: validatePass }]
+      },
+      loading: false,
+      pwdType: 'password'
+    }
+  },
+  methods: {
+    showPwd() {
+      if (this.pwdType === 'password') {
+        this.pwdType = ''
+      } else {
+        this.pwdType = 'password'
+      }
+    },
+    handleLogin() {
+      this.$refs.loginForm.validate(valid => {
+        if (valid) {
+          this.loading = true
+          this.$store.dispatch('Login', this.loginForm).then(() => {
+            this.loading = false
+            this.$router.push({ path: '/' })
+          }).catch(() => {
+            this.loading = false
+          })
+        } else {
+          console.log('error submit!!')
+          return false
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style rel="stylesheet/scss" lang="scss">
+$bg:#2d3a4b;
+$light_gray:#eee;
+
+/* reset element-ui css */
+.login-container {
+  .el-input {
+    display: inline-block;
+    height: 47px;
+    width: 85%;
+    input {
+      background: transparent;
+      border: 0px;
+      -webkit-appearance: none;
+      border-radius: 0px;
+      padding: 12px 5px 12px 15px;
+      color: $light_gray;
+      height: 47px;
+      &:-webkit-autofill {
+        -webkit-box-shadow: 0 0 0px 1000px $bg inset !important;
+        -webkit-text-fill-color: #fff !important;
+      }
+    }
+  }
+  .el-form-item {
+    border: 1px solid rgba(255, 255, 255, 0.1);
+    background: rgba(0, 0, 0, 0.1);
+    border-radius: 5px;
+    color: #454545;
+  }
+}
+
+</style>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+$bg:#2d3a4b;
+$dark_gray:#889aa4;
+$light_gray:#eee;
+.login-container {
+  position: fixed;
+  height: 100%;
+  width: 100%;
+  background-color: $bg;
+  .login-form {
+    position: absolute;
+    left: 0;
+    right: 0;
+    width: 520px;
+    padding: 35px 35px 15px 35px;
+    margin: 120px auto;
+  }
+  .svg-container {
+    padding: 6px 5px 6px 15px;
+    color: $dark_gray;
+    vertical-align: middle;
+    width: 30px;
+    display: inline-block;
+    &_login {
+      font-size: 20px;
+    }
+  }
+  .title {
+    font-size: 26px;
+    font-weight: 400;
+    color: $light_gray;
+    margin: 0px auto 40px auto;
+    text-align: center;
+    font-weight: bold;
+  }
+  .show-pwd {
+    position: absolute;
+    right: 10px;
+    top: 7px;
+    font-size: 16px;
+    color: $dark_gray;
+    cursor: pointer;
+    user-select: none;
+  }
+}
+</style>
diff --git a/leave-school-vue/src/views/news/newspublish/index.vue b/leave-school-vue/src/views/news/newspublish/index.vue
new file mode 100644
index 0000000..a83a8fd
--- /dev/null
+++ b/leave-school-vue/src/views/news/newspublish/index.vue
@@ -0,0 +1,257 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <el-row :gutter="20">
+        <el-col :span="5">
+          <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="公告标题" v-model="listQuery.ggbt">
+          </el-input>
+        </el-col>
+        <el-col :span="5">
+          <el-date-picker
+            v-model="listQuery.fbqssj"
+            type="date"
+            placeholder="发布起始时间">
+          </el-date-picker>
+        </el-col>
+        <el-col :span="5">
+          <el-date-picker
+            v-model="listQuery.fbjssj"
+            type="date"
+            placeholder="发布结束时间">
+          </el-date-picker>
+        </el-col>
+        <el-col :span="9">
+          <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">查询</el-button>
+          <el-button class="filter-item" style="margin-left: 10px;" @click="handleCreate(null, 'create')" type="primary" icon="el-icon-edit">添加</el-button>
+          <el-button class="filter-item" style="margin-left: 10px;" @click="handleReset" type="primary" icon="el-icon-edit">重置</el-button>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="5">
+          <el-select class="filter-item" v-model="temp.sfky" placeholder="是否可用">
+            <el-option key="1" label="可用" value="1">
+            </el-option>
+            <el-option key="0" label="不可用" value="0">
+            </el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="5">
+          <el-select clearable class="filter-item" v-model="listQuery.xswz" placeholder="显示位置">
+            <el-option v-for="item in  xswzList" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="5">
+          <el-select clearable class="filter-item" v-model="listQuery.jlckzt" placeholder="记录查看状态">
+            <el-option key="1" label="需要" value="1">
+            </el-option>
+            <el-option key="0" label="不需要" value="0">
+            </el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="9">
+        </el-col>
+      </el-row>
+    </div>
+    <el-table :height="height" :data="items" v-loading="listLoading" element-loading-text="Loading" border fit highlight-current-row>
+      <el-table-column align="center" type="index" label='序号' width="95">
+      </el-table-column>
+      <el-table-column label="公告标题" align="center">
+        <template slot-scope="scope">
+          {{scope.row.ggbt}}
+        </template>
+      </el-table-column>
+      <el-table-column label="公告类型" align="center">
+        <template slot-scope="scope">
+          <span>{{scope.row.gglx}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="接收者类型" align="center">
+        <template slot-scope="scope">
+          {{scope.row.jszlx}}
+        </template>
+      </el-table-column>
+      <el-table-column label="是否可用" align="center">
+        <template slot-scope="scope">
+          {{scope.row.sfky}}
+        </template>
+      </el-table-column>
+      <el-table-column label="发布起始时间" align="center">
+        <template slot-scope="scope">
+          {{scope.row.fbqssj}}
+        </template>
+      </el-table-column>
+      <el-table-column label="发布结束时间" align="center">
+        <template slot-scope="scope">
+          {{scope.row.fbjssj}}
+        </template>
+      </el-table-column>
+      <el-table-column label="显示位置设置" align="center">
+        <template slot-scope="scope">
+          {{scope.row.xswz}}
+        </template>
+      </el-table-column>
+      <el-table-column label="点击数" align="center">
+        <template slot-scope="scope">
+          {{scope.row.djs}}
+        </template>
+      </el-table-column>
+      <el-table-column
+        fixed="right"
+        header-align="center"
+        align="center"
+        width="150"
+        label="操作">
+        <template slot-scope="scope">
+          <el-button type="text" size="small" @click="handleCreate(scope.row.id, 'update')">修改</el-button>
+          <el-button type="text" size="small" @click="handleDelete(scope.row.id)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <div class="pagination-container">
+      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.pageIndex" :page-sizes="[10,20,30, 50]" :page-size="listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="recordCount">
+      </el-pagination>
+    </div>
+
+    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="80%" top="10vh">
+      <el-form :rules="rules" ref="dataForm" :model="temp" label-position="left" label-width="150px" style='margin-left:50px;'>
+        <el-form-item label="公告标题" prop="ggbt">
+          <el-input v-model="temp.ggbt"></el-input>
+          <input type="hidden" v-model="temp.id" />
+        </el-form-item>
+        <el-form-item label="是否可用" prop="sfky">
+          <el-select class="filter-item" v-model="temp.sfky" placeholder="是否可用">
+            <el-option key="1" label="可用" value="1">
+            </el-option>
+            <el-option key="0" label="不可用" value="0">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="发布开始时间">
+          <el-date-picker
+            v-model="temp.fbqssj"
+            type="date"
+            placeholder="选择日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="发布结束时间">
+          <el-date-picker
+            v-model="temp.fbjssj"
+            type="date"
+            placeholder="选择日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="记录查看状态">
+          <el-select class="filter-item" v-model="temp.jlckzt" placeholder="请选择">
+            <el-option key="1" label="需要" value="1">
+            </el-option>
+            <el-option key="0" label="不需要" value="0">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="显示位置" prop="xswz">
+          <el-select class="filter-item" v-model="temp.xswz" placeholder="请选择">
+            <el-option v-for="item in xswzList" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="接收者类型">
+          <el-radio-group v-model="temp.jszlx">
+            <el-radio v-for="item in jszlxList" :label="item.id" :key="item.id" >{{item.name}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="公告内容">
+          <div class="editor-container">
+            <UE v-model="temp.ggnr" :config=config ref="ue"></UE>
+          </div>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogFormVisible = false">返回</el-button>
+        <el-button type="primary" @click="createData">提交</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getList, getItem, createNewspublish, deleteNewspublish } from '@/api/newspublish-api'
+import { getDicList } from '@/api/dictionary-api'
+import waves from '@/directive/waves' // 水波纹指令
+import { resetForm } from '@/utils'
+import { crudPageList, crudGetItem, crudCreate, crudDelete } from '@/utils/crud'
+import mixindata from '@/utils/crud'
+import UE from '@/components/UEditor'
+
+const initData = { sfky: '1', xswz: '14', jszlx: '16', ggnr: '' }
+export default {
+  name: 'newspublish',
+  components: { UE },
+  directives: {
+    waves
+  },
+  mixins: [mixindata],
+  data() {
+    return {
+      config: {
+        initialFrameWidth: null,
+        initialFrameHeight: 350
+      },
+      xswzList: [],
+      jszlxList: [],
+      rules: {
+        ggbt: [{ required: true, message: '公告标题必填', trigger: 'blur' }],
+        sfky: [{ required: true, message: '是否可用必选', trigger: 'change' }],
+        xswz: [{ required: true, message: '显示位置必选', trigger: 'change' }]
+      }
+    }
+  },
+  created() {
+    this.getXswzList()
+    this.getJszlxList()
+    this.handlePageList()
+    this.height = window.innerHeight - 266
+  },
+  methods: {
+    getXswzList() {
+      getDicList({ type: 'xswz' }).then(response => {
+        this.xswzList = response.items
+      })
+    },
+    getJszlxList() {
+      getDicList({ type: 'jszlx' }).then(response => {
+        this.jszlxList = response.items
+      })
+    },
+    handlePageList() {
+      crudPageList(this, getList)
+    },
+    handleCreate(rowid, dialogStatus) {
+      this.dialogStatus = dialogStatus
+      crudGetItem(this, getItem, rowid, initData)
+    },
+    handleReset() {
+      resetForm(this.listQuery)
+    },
+    handleFilter() {
+      this.listQuery.pageIndex = 1
+      this.handlePageList()
+    },
+    handleSizeChange(val) {
+      this.listQuery.pageSize = val
+      this.handlePageList()
+    },
+    handleCurrentChange(val) {
+      this.listQuery.pageIndex = val
+      this.handlePageList()
+    },
+    createData() {
+      this.temp.ggnr = this.$refs.ue.getUEContent()
+      crudCreate(this, createNewspublish, this.handlePageList)
+    },
+    handleDelete(rowid) {
+      crudDelete(this, deleteNewspublish, rowid, this.handlePageList)
+    }
+  }
+}
+</script>
diff --git a/leave-school-vue/src/views/news/newview/index.vue b/leave-school-vue/src/views/news/newview/index.vue
new file mode 100644
index 0000000..09a9ab3
--- /dev/null
+++ b/leave-school-vue/src/views/news/newview/index.vue
@@ -0,0 +1,107 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <el-row :gutter="20">
+        <el-col :span="4">
+          <el-select clearable class="filter-item" v-model="listQuery.gglx" placeholder="类型名称">
+            <el-option v-for="item in  gglxList" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="4">
+          <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="公告标题" v-model="listQuery.ggbt">
+          </el-input>
+        </el-col>
+        <el-col :span="12">
+          <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">查询</el-button>
+          <el-button class="filter-item" style="margin-left: 10px;" @click="handleReset" type="primary" icon="el-icon-edit">重置</el-button>
+        </el-col>
+      </el-row>
+    </div>
+    <el-table :height="height" :data="items" v-loading="listLoading" element-loading-text="Loading" border fit highlight-current-row>
+      <el-table-column align="center" type="index" label='序号' width="95">
+      </el-table-column>
+      <el-table-column label="类型名称" align="center">
+        <template slot-scope="scope">
+          {{scope.row.gglx}}
+        </template>
+      </el-table-column>
+      <el-table-column label="公告标题" align="center">
+        <template slot-scope="scope">
+          <span>{{scope.row.ggbt}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="接收对象类型" align="center">
+        <template slot-scope="scope">
+          {{scope.row.jszlx}}
+        </template>
+      </el-table-column>
+      <el-table-column label="发布人" align="center">
+        <template slot-scope="scope">
+          {{scope.row.fbr}}
+        </template>
+      </el-table-column>
+      <el-table-column label="发布日期" align="center">
+        <template slot-scope="scope">
+          {{scope.row.fbrq}}
+        </template>
+      </el-table-column>
+    </el-table>
+    <div class="pagination-container">
+      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.pageIndex" :page-sizes="[10,20,30, 50]" :page-size="listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="recordCount">
+      </el-pagination>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getList } from '@/api/newspublish-api'
+import { getDicList } from '@/api/dictionary-api'
+import waves from '@/directive/waves' // 水波纹指令
+import { resetForm } from '@/utils'
+import { crudPageList } from '@/utils/crud'
+import mixindata from '@/utils/crud'
+
+export default {
+  name: 'newview',
+  directives: {
+    waves
+  },
+  mixins: [mixindata],
+  data() {
+    return {
+      gglxList: []
+    }
+  },
+  created() {
+    this.getGglxList()
+    this.handlePageList()
+    this.height = window.innerHeight - 216
+  },
+  methods: {
+    getGglxList() {
+      getDicList({ type: 'gglx' }).then(response => {
+        this.gglxList = response.items
+      })
+    },
+    handlePageList() {
+      crudPageList(this, getList)
+    },
+    handleReset() {
+      resetForm(this.listQuery)
+    },
+    handleFilter() {
+      this.listQuery.pageIndex = 1
+      this.handlePageList()
+    },
+    handleSizeChange(val) {
+      this.listQuery.pageSize = val
+      this.handlePageList()
+    },
+    handleCurrentChange(val) {
+      this.listQuery.pageIndex = val
+      this.handlePageList()
+    }
+  }
+}
+</script>
diff --git a/leave-school-vue/src/views/systemmanagement/auditscope/index.vue b/leave-school-vue/src/views/systemmanagement/auditscope/index.vue
new file mode 100644
index 0000000..7a37094
--- /dev/null
+++ b/leave-school-vue/src/views/systemmanagement/auditscope/index.vue
@@ -0,0 +1,129 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="范围名称" v-model="listQuery.fwkzmc">
+      </el-input>
+      <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">查询</el-button>
+      <el-button class="filter-item" style="margin-left: 10px;" @click="handleCreate(null, 'create')" type="primary" icon="el-icon-edit">添加</el-button>
+      <el-button class="filter-item" style="margin-left: 10px;" @click="handleReset" type="primary" icon="el-icon-edit">重置</el-button>
+    </div>
+    <el-table :height="height" :data="items" v-loading="listLoading" element-loading-text="Loading" border fit highlight-current-row>
+      <el-table-column align="center" label='范围控制代码' width="195">
+        <template slot-scope="scope">
+          {{scope.row.id}}
+        </template>
+      </el-table-column>
+      <el-table-column label="范围控制名称" align="center">
+        <template slot-scope="scope">
+          {{scope.row.fwkzmc}}
+        </template>
+      </el-table-column>
+      <el-table-column label="范围控制实现类" align="center">
+        <template slot-scope="scope">
+          <span>{{scope.row.fwkzsxl}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column
+        fixed="right"
+        header-align="center"
+        align="center"
+        width="150"
+        label="操作">
+        <template slot-scope="scope">
+          <el-button type="text" size="small" @click="handleCreate(scope.row.id, 'update')">修改</el-button>
+          <el-button type="text" size="small" @click="handleDelete(scope.row.id)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <div class="pagination-container">
+      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.pageIndex" :page-sizes="[10,20,30, 50]" :page-size="listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="recordCount">
+      </el-pagination>
+    </div>
+
+    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
+      <el-form :rules="rules" ref="dataForm" :model="temp" label-position="left" label-width="150px" style='width: 400px; margin-left:50px;'>
+        <el-form-item label="范围控制名称" prop="fwkzmc">
+          <el-input v-model="temp.fwkzmc"></el-input>
+          <input type="hidden" v-model="temp.id" />
+        </el-form-item>
+        <el-form-item label="范围控制实现类" prop="fwkzsxl">
+          <el-input v-model="temp.fwkzsxl"></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogFormVisible = false">返回</el-button>
+        <el-button type="primary" @click="createData">提交</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getList, getItem, createAuditScope, deleteAuditScope } from '@/api/auditscope-api'
+import waves from '@/directive/waves' // 水波纹指令
+import { resetForm } from '@/utils'
+import { crudPageList, crudGetItem, crudCreate, crudDelete } from '@/utils/crud'
+import mixindata from '@/utils/crud'
+
+const initData = { sfky: '1' }
+export default {
+  name: 'auditscope',
+  directives: {
+    waves
+  },
+  mixins: [mixindata],
+  data() {
+    return {
+      ssyxList: [],
+      sszygbList: [],
+      rules: {
+        fwkzmc: [{ required: true, message: '范围控制名称必填', trigger: 'blur' }],
+        fwkzsxl: [{ required: true, message: '范围控制实现类必填', trigger: 'blur' }]
+      }
+    }
+  },
+  filters: {
+    statusFilter(status) {
+      const statusMap = {
+        '1': 'success',
+        '0': 'danger'
+      }
+      return statusMap[status]
+    }
+  },
+  created() {
+    this.handlePageList()
+    this.height = window.innerHeight - 216
+  },
+  methods: {
+    handlePageList() {
+      crudPageList(this, getList)
+    },
+    handleCreate(rowid, dialogStatus) {
+      this.dialogStatus = dialogStatus
+      crudGetItem(this, getItem, rowid, initData)
+    },
+    handleReset() {
+      resetForm(this.listQuery)
+    },
+    handleFilter() {
+      this.listQuery.pageIndex = 1
+      this.handlePageList()
+    },
+    handleSizeChange(val) {
+      this.listQuery.pageSize = val
+      this.handlePageList()
+    },
+    handleCurrentChange(val) {
+      this.listQuery.pageIndex = val
+      this.handlePageList()
+    },
+    createData() {
+      crudCreate(this, createAuditScope, this.handlePageList)
+    },
+    handleDelete(rowid) {
+      crudDelete(this, deleteAuditScope, rowid, this.handlePageList)
+    }
+  }
+}
+</script>
diff --git a/leave-school-vue/src/views/systemmanagement/autoaudittype/index.vue b/leave-school-vue/src/views/systemmanagement/autoaudittype/index.vue
new file mode 100644
index 0000000..9bcaa4e
--- /dev/null
+++ b/leave-school-vue/src/views/systemmanagement/autoaudittype/index.vue
@@ -0,0 +1,129 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="自动审核类型名称" v-model="listQuery.zdshlxmc">
+      </el-input>
+      <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">查询</el-button>
+      <el-button class="filter-item" style="margin-left: 10px;" @click="handleCreate(null, 'create')" type="primary" icon="el-icon-edit">添加</el-button>
+      <el-button class="filter-item" style="margin-left: 10px;" @click="handleReset" type="primary" icon="el-icon-edit">重置</el-button>
+    </div>
+    <el-table :height="height" :data="items" v-loading="listLoading" element-loading-text="Loading" border fit highlight-current-row>
+      <el-table-column align="center" label='自动审核类型代码' width="195">
+        <template slot-scope="scope">
+          {{scope.row.id}}
+        </template>
+      </el-table-column>
+      <el-table-column label="自动审核类型名称" align="center">
+        <template slot-scope="scope">
+          {{scope.row.zdshlxmc}}
+        </template>
+      </el-table-column>
+      <el-table-column label="自动审核类型实现类" align="center">
+        <template slot-scope="scope">
+          <span>{{scope.row.zdshlxsxl}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column
+        fixed="right"
+        header-align="center"
+        align="center"
+        width="150"
+        label="操作">
+        <template slot-scope="scope">
+          <el-button type="text" size="small" @click="handleCreate(scope.row.id, 'update')">修改</el-button>
+          <el-button type="text" size="small" @click="handleDelete(scope.row.id)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <div class="pagination-container">
+      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.pageIndex" :page-sizes="[10,20,30, 50]" :page-size="listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="recordCount">
+      </el-pagination>
+    </div>
+
+    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
+      <el-form :rules="rules" ref="dataForm" :model="temp" label-position="left" label-width="150px" style='width: 400px; margin-left:50px;'>
+        <el-form-item label="自动审核类型名称" prop="zdshlxmc">
+          <el-input v-model="temp.zdshlxmc"></el-input>
+          <input type="hidden" v-model="temp.id" />
+        </el-form-item>
+        <el-form-item label="自动审核类型实现类" prop="zdshlxsxl">
+          <el-input v-model="temp.zdshlxsxl"></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogFormVisible = false">返回</el-button>
+        <el-button type="primary" @click="createData">提交</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getList, getItem, createAutoAuditType, deleteAutoAuditType } from '@/api/autoaudittype-api'
+import waves from '@/directive/waves' // 水波纹指令
+import { resetForm } from '@/utils'
+import { crudPageList, crudGetItem, crudCreate, crudDelete } from '@/utils/crud'
+import mixindata from '@/utils/crud'
+
+const initData = { sfky: '1' }
+export default {
+  name: 'autoaudittype',
+  directives: {
+    waves
+  },
+  mixins: [mixindata],
+  data() {
+    return {
+      ssyxList: [],
+      sszygbList: [],
+      rules: {
+        zdshlxmc: [{ required: true, message: '自动审核类型名称必填', trigger: 'blur' }],
+        zdshlxsxl: [{ required: true, message: '自动审核类型实现类必填', trigger: 'blur' }]
+      }
+    }
+  },
+  filters: {
+    statusFilter(status) {
+      const statusMap = {
+        '1': 'success',
+        '0': 'danger'
+      }
+      return statusMap[status]
+    }
+  },
+  created() {
+    this.handlePageList()
+    this.height = window.innerHeight - 216
+  },
+  methods: {
+    handlePageList() {
+      crudPageList(this, getList)
+    },
+    handleCreate(rowid, dialogStatus) {
+      this.dialogStatus = dialogStatus
+      crudGetItem(this, getItem, rowid, initData)
+    },
+    handleReset() {
+      resetForm(this.listQuery)
+    },
+    handleFilter() {
+      this.listQuery.pageIndex = 1
+      this.handlePageList()
+    },
+    handleSizeChange(val) {
+      this.listQuery.pageSize = val
+      this.handlePageList()
+    },
+    handleCurrentChange(val) {
+      this.listQuery.pageIndex = val
+      this.handlePageList()
+    },
+    createData() {
+      crudCreate(this, createAutoAuditType, this.handlePageList)
+    },
+    handleDelete(rowid) {
+      crudDelete(this, deleteAutoAuditType, rowid, this.handlePageList)
+    }
+  }
+}
+</script>
diff --git a/leave-school-vue/src/views/systemmanagement/class/index.vue b/leave-school-vue/src/views/systemmanagement/class/index.vue
new file mode 100644
index 0000000..33619b6
--- /dev/null
+++ b/leave-school-vue/src/views/systemmanagement/class/index.vue
@@ -0,0 +1,258 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <el-row :gutter="20">
+        <el-col :span="4">
+          <el-select clearable @change="initZyList" class="filter-item" v-model="listQuery.yx" placeholder="院系">
+            <el-option v-for="item in  yxList" :key="item.id" :label="item.dwmc" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="4">
+          <el-select clearable class="filter-item" v-model="listQuery.zy" placeholder="专业">
+            <el-option v-for="item in  zyList" :key="item.id" :label="item.zymc" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="4">
+          <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="班级名称" v-model="listQuery.bjmc">
+          </el-input>
+        </el-col>
+        <el-col :span="12">
+          <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">查询</el-button>
+          <el-button class="filter-item" style="margin-left: 10px;" @click="handleCreate(null, 'create')" type="primary" icon="el-icon-edit">添加</el-button>
+          <el-button class="filter-item" style="margin-left: 10px;" @click="handleReset" type="primary" icon="el-icon-edit">重置</el-button>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="4">
+          <el-select clearable @change="initZyList" class="filter-item" v-model="listQuery.nj" placeholder="年级">
+            <el-option v-for="item in  njList" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="4">
+          <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="班级代码" v-model="listQuery.bjdm">
+          </el-input>
+        </el-col>
+        <el-col :span="4">
+          <el-select clearable class="filter-item" v-model="listQuery.sfky" placeholder="是否可用">
+            <el-option key="1" label="可用" value="1">
+            </el-option>
+            <el-option key="0" label="不可用" value="0">
+            </el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="12">
+        </el-col>
+      </el-row>
+    </div>
+    <el-table :height="height" :data="items" v-loading="listLoading" element-loading-text="Loading" border fit highlight-current-row>
+      <el-table-column fixed align="center" label='序号' width="95">
+        <template slot-scope="scope">
+          {{scope.row.id}}
+        </template>
+      </el-table-column>
+      <el-table-column label="年级" align="center">
+        <template slot-scope="scope">
+          {{scope.row.njmc}}
+        </template>
+      </el-table-column>
+      <el-table-column label="院系" align="center">
+        <template slot-scope="scope">
+          {{scope.row.yxmc}}
+        </template>
+      </el-table-column>
+      <el-table-column label="专业" align="center">
+        <template slot-scope="scope">
+          {{scope.row.zymc}}
+        </template>
+      </el-table-column>
+      <el-table-column label="班级代码" align="center">
+        <template slot-scope="scope">
+          {{scope.row.bjdm}}
+        </template>
+      </el-table-column>
+      <el-table-column label="班级名称" align="center">
+        <template slot-scope="scope">
+          {{scope.row.bjmc}}
+        </template>
+      </el-table-column>
+      <el-table-column label="是否可用" align="center">
+        <template slot-scope="scope">
+          {{scope.row.sfkymc}}
+        </template>
+      </el-table-column>
+      <el-table-column
+        fixed="right"
+        header-align="center"
+        align="center"
+        width="150"
+        label="操作">
+        <template slot-scope="scope">
+          <el-button type="text" size="small" @click="handleCreate(scope.row.id, 'update')">修改</el-button>
+          <el-button type="text" size="small" @click="handleDelete(scope.row.id)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <div class="pagination-container">
+      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.pageIndex" 
+      :page-sizes="[10,20,30, 50]" :page-size="listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="recordCount">
+      </el-pagination>
+    </div>
+    
+    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
+      <el-form :rules="rules" ref="dataForm" :model="temp" label-position="left" label-width="150px" style='width: 400px; margin-left:50px;'>
+        <el-form-item label="班级代码" prop="bjdm">
+          <el-input v-model="temp.bjdm"></el-input>
+        </el-form-item>
+        <el-form-item label="班级名称" prop="bjmc">
+          <el-input v-model="temp.bjmc"></el-input>
+        </el-form-item>
+        <el-form-item label="院系" prop="yx">
+          <el-select class="filter-item" @change="initFormZyList" v-model="temp.yx" placeholder="--请选择--">
+            <el-option v-for="item in  yxList" :key="item.id" :label="item.dwmc" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="专业" prop="zy">
+          <el-select class="filter-item" v-model="temp.zy" placeholder="--请选择--">
+            <el-option v-for="item in  formZyList" :key="item.id" :label="item.zymc" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="年级" prop="nj">
+          <el-select class="filter-item" v-model="temp.nj" placeholder="--请选择--">
+            <el-option v-for="item in  njList" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="是否可用">
+          <el-select class="filter-item" v-model="temp.sfky" placeholder="--请选择--">
+            <el-option key="1" label="可用" value="1">
+            </el-option>
+            <el-option key="0" label="不可用" value="0">
+            </el-option>
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogFormVisible = false">返回</el-button>
+        <el-button type="primary" @click="createData">提交</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getList, getItem, createClass, deleteClass } from '@/api/class-api'
+import { getDicList } from '@/api/dictionary-api'
+import { getAllList as getAllDeptList } from '@/api/department-api'
+import { getZyListByYx } from '@/api/major-api'
+import waves from '@/directive/waves' // 水波纹指令
+import { resetForm } from '@/utils'
+import { crudPageList, crudGetItem, crudCreate, crudDelete } from '@/utils/crud'
+import mixindata from '@/utils/crud'
+
+const initData = { sfky: '1' }
+export default {
+  name: 'class',
+  directives: {
+    waves
+  },
+  mixins: [mixindata],
+  data() {
+    return {
+      yxList: [],
+      zyList: [],
+      formZyList: [],
+      njList: [],
+      rules: {
+        bjdm: [{ required: true, message: '班级代码必填', trigger: 'blur' }],
+        bjmc: [{ required: true, message: '班级名称必填', trigger: 'blur' }],
+        yx: [{ required: true, message: '院系必选', trigger: 'change' }],
+        zy: [{ required: true, message: '专业必选', trigger: 'change' }],
+        nj: [{ required: true, message: '年级必选', trigger: 'change' }]
+      }
+    }
+  },
+  filters: {
+    statusFilter(status) {
+      const statusMap = {
+        '1': 'success',
+        '0': 'danger'
+      }
+      return statusMap[status]
+    }
+  },
+  created() {
+    this.initYxList()
+    this.initZyList()
+    this.initNjList()
+    this.handlePageList()
+    this.height = window.innerHeight - 266
+  },
+  methods: {
+    initYxList() {
+      getAllDeptList(this.listQuery).then(response => {
+        this.yxList = response.items
+      })
+    },
+    initZyList() {
+      getZyListByYx({ yx: this.listQuery.yx }).then(response => {
+        this.zyList = response.items
+        // TODO 坑,this.listQuery.zy == null 直接赋值,专业下拉框选择出bug,无法选择,原因未知
+        for (const attr in this.listQuery) {
+          if (attr === 'zy') {
+            this.listQuery['zy'] = null
+          }
+        }
+      })
+    },
+    initFormZyList() {
+      getZyListByYx({ yx: this.temp.yx }).then(response => {
+        this.formZyList = response.items
+        // TODO 坑,this.listQuery.zy == null 直接赋值,专业下拉框选择出bug,无法选择,原因未知
+        for (const attr in this.temp) {
+          if (attr === 'zy') {
+            this.temp['zy'] = null
+          }
+        }
+      })
+    },
+    initNjList() {
+      getDicList({ type: 'nj' }).then(response => {
+        this.njList = response.items
+      })
+    },
+    handlePageList() {
+      crudPageList(this, getList)
+    },
+    handleCreate(rowid, dialogStatus) {
+      this.dialogStatus = dialogStatus
+      crudGetItem(this, getItem, rowid, initData)
+    },
+    handleReset() {
+      resetForm(this.listQuery)
+    },
+    handleFilter() {
+      this.listQuery.pageIndex = 1
+      this.handlePageList()
+    },
+    handleSizeChange(val) {
+      this.listQuery.pageSize = val
+      this.handlePageList()
+    },
+    handleCurrentChange(val) {
+      this.listQuery.pageIndex = val
+      this.handlePageList()
+    },
+    createData() {
+      crudCreate(this, createClass, this.handlePageList)
+    },
+    handleDelete(rowid) {
+      crudDelete(this, deleteClass, rowid, this.handlePageList)
+    }
+  }
+}
+</script>
diff --git a/leave-school-vue/src/views/systemmanagement/department/index.vue b/leave-school-vue/src/views/systemmanagement/department/index.vue
new file mode 100644
index 0000000..d1c71bc
--- /dev/null
+++ b/leave-school-vue/src/views/systemmanagement/department/index.vue
@@ -0,0 +1,197 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="单位代码" v-model="listQuery.dwdm">
+      </el-input>
+      <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="单位名称" v-model="listQuery.dwmc">
+      </el-input>
+      <el-select clearable class="filter-item" v-model="listQuery.sfqy" placeholder="是否启用">
+        <el-option key="1" label="启用" value="1">
+        </el-option>
+        <el-option key="0" label="未启用" value="0">
+        </el-option>
+      </el-select>
+      <el-select clearable class="filter-item" v-model="listQuery.lbm" placeholder="类别码">
+        <el-option v-for="item in  lbmList" :key="item.id" :label="item.name" :value="item.id">
+        </el-option>
+      </el-select>
+      <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">查询</el-button>
+      <el-button class="filter-item" style="margin-left: 10px;" @click="handleCreate(null, 'create')" type="primary" icon="el-icon-edit">添加</el-button>
+      <el-button class="filter-item" style="margin-left: 10px;" @click="handleReset" type="primary" icon="el-icon-edit">重置</el-button>
+    </div>
+    <el-table :height="height" :data="items" v-loading="listLoading" element-loading-text="Loading" border fit highlight-current-row>
+      <el-table-column fixed align="center" label='序号' width="95">
+        <template slot-scope="scope">
+          {{scope.row.id}}
+        </template>
+      </el-table-column>
+      <el-table-column fixed label="单位代码">
+        <template slot-scope="scope">
+          {{scope.row.dwdm}}
+        </template>
+      </el-table-column>
+      <el-table-column label="单位名称" align="center">
+        <template slot-scope="scope">
+          <span>{{scope.row.dwmc}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="单位简称" align="center">
+        <template slot-scope="scope">
+          {{scope.row.dwjc}}
+        </template>
+      </el-table-column>
+      <el-table-column label="单位英文名称" align="center">
+        <template slot-scope="scope">
+          {{scope.row.dwywmc}}
+        </template>
+      </el-table-column>
+      <el-table-column label="是否启用" align="center">
+        <template slot-scope="scope">
+          {{scope.row.sfqy}}
+        </template>
+      </el-table-column>
+      <el-table-column class-name="status-col" label="类别码" width="110" align="center">
+        <template slot-scope="scope">
+          <el-tag :type="scope.row.lbm | statusFilter">{{scope.row.lbm}}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" prop="created_at" label="创建时间" width="200">
+        <template slot-scope="scope">
+          <i class="el-icon-time"></i>
+          {{scope.row.cjsj}}
+        </template>
+      </el-table-column>
+      <el-table-column
+        fixed="right"
+        header-align="center"
+        align="center"
+        width="150"
+        label="操作">
+        <template slot-scope="scope">
+          <el-button type="text" size="small" @click="handleCreate(scope.row.id, 'update')">修改</el-button>
+          <el-button type="text" size="small" @click="handleDelete(scope.row.id)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <div class="pagination-container">
+      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.pageIndex" 
+      :page-sizes="[10,20,30, 50]" :page-size="listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="recordCount">
+      </el-pagination>
+    </div>
+    
+    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
+      <el-form :rules="rules" ref="dataForm" :model="temp" label-position="left" label-width="150px" style='width: 400px; margin-left:50px;'>
+        <el-form-item label="单位代码" prop="dwdm">
+          <el-input v-model="temp.dwdm"></el-input>
+          <input type="hidden" v-model="temp.id" />
+        </el-form-item>
+        <el-form-item label="单位名称" prop="dwmc">
+          <el-input v-model="temp.dwmc"></el-input>
+        </el-form-item>
+        <el-form-item label="单位简称" prop="dwjc">
+          <el-input v-model="temp.dwjc"></el-input>
+        </el-form-item>
+        <el-form-item label="单位英文名称" prop="dwywmc">
+          <el-input v-model="temp.dwywmc"></el-input>
+        </el-form-item>
+        <el-form-item label="排序" prop="px">
+          <el-input v-model="temp.px"></el-input>
+        </el-form-item>
+        <el-form-item label="类别码">
+          <el-select class="filter-item" v-model="temp.lbm" placeholder="请选择">
+            <el-option v-for="item in  lbmList" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="是否启用">
+          <el-select class="filter-item" v-model="temp.sfqy" placeholder="请选择">
+            <el-option key="1" label="启用" value="1">
+            </el-option>
+            <el-option key="0" label="未启用" value="0">
+            </el-option>
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogFormVisible = false">返回</el-button>
+        <el-button type="primary" @click="createData">提交</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getList, getItem, createDepartment, deleteDepartment } from '@/api/department-api'
+import { getDicList } from '@/api/dictionary-api'
+import waves from '@/directive/waves' // 水波纹指令
+import { resetForm } from '@/utils'
+import { crudPageList, crudGetItem, crudCreate, crudDelete } from '@/utils/crud'
+import mixindata from '@/utils/crud'
+
+const initData = { sfqy: '1' }
+export default {
+  name: 'department',
+  directives: {
+    waves
+  },
+  mixins: [mixindata],
+  data() {
+    return {
+      lbmList: [],
+      rules: {
+        dwdm: [{ required: true, message: '单位代码必填', trigger: 'blur' }],
+        dwmc: [{ required: true, message: '单位名称必填', trigger: 'blur' }]
+      }
+    }
+  },
+  filters: {
+    statusFilter(status) {
+      const statusMap = {
+        '1': 'success',
+        '0': 'danger'
+      }
+      return statusMap[status]
+    }
+  },
+  created() {
+    this.getLbmList()
+    this.handlePageList()
+    this.height = window.innerHeight - 216
+  },
+  methods: {
+    getLbmList() {
+      getDicList({ type: 'lbm' }).then(response => {
+        this.lbmList = response.items
+      })
+    },
+    handlePageList() {
+      crudPageList(this, getList)
+    },
+    handleCreate(rowid, dialogStatus) {
+      this.dialogStatus = dialogStatus
+      crudGetItem(this, getItem, rowid, initData)
+    },
+    handleReset() {
+      resetForm(this.listQuery)
+    },
+    handleFilter() {
+      this.listQuery.pageIndex = 1
+      this.handlePageList()
+    },
+    handleSizeChange(val) {
+      this.listQuery.pageSize = val
+      this.handlePageList()
+    },
+    handleCurrentChange(val) {
+      this.listQuery.pageIndex = val
+      this.handlePageList()
+    },
+    createData() {
+      crudCreate(this, createDepartment, this.handlePageList)
+    },
+    handleDelete(rowid) {
+      crudDelete(this, deleteDepartment, rowid, this.handlePageList)
+    }
+  }
+}
+</script>
diff --git a/leave-school-vue/src/views/systemmanagement/major/index.vue b/leave-school-vue/src/views/systemmanagement/major/index.vue
new file mode 100644
index 0000000..2738ff7
--- /dev/null
+++ b/leave-school-vue/src/views/systemmanagement/major/index.vue
@@ -0,0 +1,190 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="专业代码" v-model="listQuery.zydm">
+      </el-input>
+      <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="专业名称" v-model="listQuery.zymc">
+      </el-input>
+      <el-select clearable class="filter-item" v-model="listQuery.sfky" placeholder="是否可用">
+        <el-option key="1" label="可用" value="1">
+        </el-option>
+        <el-option key="0" label="不可用" value="0">
+        </el-option>
+      </el-select>
+      <el-select clearable class="filter-item" v-model="listQuery.ssyx" placeholder="所属院系">
+        <el-option v-for="item in  ssyxList" :key="item.id" :label="item.dwmc" :value="item.id">
+        </el-option>
+      </el-select>
+      <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">查询</el-button>
+      <el-button class="filter-item" style="margin-left: 10px;" @click="handleCreate(null, 'create')" type="primary" icon="el-icon-edit">添加</el-button>
+      <el-button class="filter-item" style="margin-left: 10px;" @click="handleReset" type="primary" icon="el-icon-edit">重置</el-button>
+    </div>
+    <el-table :height="height" :data="items" v-loading="listLoading" element-loading-text="Loading" border fit highlight-current-row>
+      <el-table-column align="center" label='序号' width="95">
+        <template slot-scope="scope">
+          {{scope.row.id}}
+        </template>
+      </el-table-column>
+      <el-table-column label="专业代码" align="center">
+        <template slot-scope="scope">
+          {{scope.row.zydm}}
+        </template>
+      </el-table-column>
+      <el-table-column label="专业名称" align="center">
+        <template slot-scope="scope">
+          <span>{{scope.row.zymc}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="是否可用" align="center">
+        <template slot-scope="scope">
+          {{scope.row.sfky}}
+        </template>
+      </el-table-column>
+      <el-table-column label="所属院系" align="center">
+        <template slot-scope="scope">
+          {{scope.row.ssyx}}
+        </template>
+      </el-table-column>
+      <el-table-column label="所属专业(国标)" align="center">
+        <template slot-scope="scope">
+          {{scope.row.sszygb}}
+        </template>
+      </el-table-column>
+      <el-table-column
+        fixed="right"
+        header-align="center"
+        align="center"
+        width="150"
+        label="操作">
+        <template slot-scope="scope">
+          <el-button type="text" size="small" @click="handleCreate(scope.row.id, 'update')">修改</el-button>
+          <el-button type="text" size="small" @click="handleDelete(scope.row.id)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <div class="pagination-container">
+      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.pageIndex" :page-sizes="[10,20,30, 50]" :page-size="listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="recordCount">
+      </el-pagination>
+    </div>
+
+    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
+      <el-form :rules="rules" ref="dataForm" :model="temp" label-position="left" label-width="150px" style='width: 400px; margin-left:50px;'>
+        <el-form-item label="专业代码" prop="zydm">
+          <el-input v-model="temp.zydm"></el-input>
+          <input type="hidden" v-model="temp.id" />
+        </el-form-item>
+        <el-form-item label="专业名称" prop="zymc">
+          <el-input v-model="temp.zymc"></el-input>
+        </el-form-item>
+        <el-form-item label="所在院系">
+          <el-select class="filter-item" v-model="temp.ssyx" placeholder="请选择">
+            <el-option v-for="item in  ssyxList" :key="item.id" :label="item.dwmc" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="是否可用">
+          <el-select class="filter-item" v-model="temp.sfky" placeholder="请选择">
+            <el-option key="1" label="可用" value="1">
+            </el-option>
+            <el-option key="0" label="不可用" value="0">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="所属专业(国标)">
+          <el-select class="filter-item" v-model="temp.sszygb" placeholder="--请选择专业(国标)--">
+            <el-option v-for="item in  sszygbList" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogFormVisible = false">返回</el-button>
+        <el-button type="primary" @click="createData">提交</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getList, getItem, createMajor, deleteMajor } from '@/api/major-api'
+import { getDicList } from '@/api/dictionary-api'
+import { getAllList as getAllDeptList } from '@/api/department-api'
+import waves from '@/directive/waves' // 水波纹指令
+import { resetForm } from '@/utils'
+import { crudPageList, crudGetItem, crudCreate, crudDelete } from '@/utils/crud'
+import mixindata from '@/utils/crud'
+
+const initData = { sfky: '1' }
+export default {
+  name: 'major',
+  directives: {
+    waves
+  },
+  mixins: [mixindata],
+  data() {
+    return {
+      ssyxList: [],
+      sszygbList: [],
+      rules: {
+        zydm: [{ required: true, message: '专业代码必填', trigger: 'blur' }],
+        zymc: [{ required: true, message: '专业名称必填', trigger: 'blur' }]
+      }
+    }
+  },
+  filters: {
+    statusFilter(status) {
+      const statusMap = {
+        '1': 'success',
+        '0': 'danger'
+      }
+      return statusMap[status]
+    }
+  },
+  created() {
+    this.getSsyxList()
+    this.getSszygbList()
+    this.handlePageList()
+    this.height = window.innerHeight - 216
+  },
+  methods: {
+    getSszygbList() {
+      getDicList({ type: 'gjzybz' }).then(response => {
+        this.sszygbList = response.items
+      })
+    },
+    getSsyxList() {
+      getAllDeptList(this.listQuery).then(response => {
+        this.ssyxList = response.items
+      })
+    },
+    handlePageList() {
+      crudPageList(this, getList)
+    },
+    handleCreate(rowid, dialogStatus) {
+      this.dialogStatus = dialogStatus
+      crudGetItem(this, getItem, rowid, initData)
+    },
+    handleReset() {
+      resetForm(this.listQuery)
+    },
+    handleFilter() {
+      this.listQuery.pageIndex = 1
+      this.handlePageList()
+    },
+    handleSizeChange(val) {
+      this.listQuery.pageSize = val
+      this.handlePageList()
+    },
+    handleCurrentChange(val) {
+      this.listQuery.pageIndex = val
+      this.handlePageList()
+    },
+    createData() {
+      crudCreate(this, createMajor, this.handlePageList)
+    },
+    handleDelete(rowid) {
+      crudDelete(this, deleteMajor, rowid, this.handlePageList)
+    }
+  }
+}
+</script>
diff --git a/leave-school-vue/src/views/systemmanagement/rostersyncinterface/index.vue b/leave-school-vue/src/views/systemmanagement/rostersyncinterface/index.vue
new file mode 100644
index 0000000..886a122
--- /dev/null
+++ b/leave-school-vue/src/views/systemmanagement/rostersyncinterface/index.vue
@@ -0,0 +1,146 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="代码" v-model="listQuery.dm">
+      </el-input>
+      <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="名称" v-model="listQuery.mc">
+      </el-input>
+      <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="条件" v-model="listQuery.tj">
+      </el-input>
+      <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="排序" v-model="listQuery.px">
+      </el-input>
+      <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">查询</el-button>
+      <el-button class="filter-item" style="margin-left: 10px;" @click="handleCreate(null, 'create')" type="primary" icon="el-icon-edit">添加</el-button>
+      <el-button class="filter-item" style="margin-left: 10px;" @click="handleReset" type="primary" icon="el-icon-edit">重置</el-button>
+    </div>
+    <el-table :height="height" :data="items" v-loading="listLoading" element-loading-text="Loading" border fit highlight-current-row>
+      <el-table-column align="center" label='代码' width="195">
+        <template slot-scope="scope">
+          {{scope.row.dm}}
+        </template>
+      </el-table-column>
+      <el-table-column label="名称" align="center">
+        <template slot-scope="scope">
+          {{scope.row.mc}}
+        </template>
+      </el-table-column>
+      <el-table-column label="条件" align="center">
+        <template slot-scope="scope">
+          <span>{{scope.row.tj}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="排序" align="center">
+        <template slot-scope="scope">
+          <span>{{scope.row.px}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column
+        fixed="right"
+        header-align="center"
+        align="center"
+        width="150"
+        label="操作">
+        <template slot-scope="scope">
+          <el-button type="text" size="small" @click="handleCreate(scope.row.id, 'update')">修改</el-button>
+          <el-button type="text" size="small" @click="handleDelete(scope.row.id)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <div class="pagination-container">
+      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.pageIndex" :page-sizes="[10,20,30, 50]" :page-size="listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="recordCount">
+      </el-pagination>
+    </div>
+
+    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
+      <el-form :rules="rules" ref="dataForm" :model="temp" label-position="left" label-width="150px" style='width: 400px; margin-left:50px;'>
+        <el-form-item label="代码" prop="dm">
+          <el-input v-model="temp.dm"></el-input>
+          <input type="hidden" v-model="temp.id" />
+        </el-form-item>
+        <el-form-item label="名称" prop="mc">
+          <el-input v-model="temp.mc"></el-input>
+        </el-form-item>
+        <el-form-item label="条件" prop="tj">
+          <el-input type="textarea" :rows="2" v-model="temp.tj"></el-input>
+        </el-form-item>
+        <el-form-item label="排序" prop="px">
+          <el-input v-model="temp.px"></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogFormVisible = false">返回</el-button>
+        <el-button type="primary" @click="createData">提交</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getList, getItem, createRosterSyncInterface, deleteRosterSyncInterface } from '@/api/rostersyncinterface-api'
+import waves from '@/directive/waves' // 水波纹指令
+import { resetForm } from '@/utils'
+import { crudPageList, crudGetItem, crudCreate, crudDelete } from '@/utils/crud'
+import mixindata from '@/utils/crud'
+
+const initData = { sfky: '1' }
+export default {
+  name: 'rostersyncinterface',
+  directives: {
+    waves
+  },
+  mixins: [mixindata],
+  data() {
+    return {
+      ssyxList: [],
+      sszygbList: [],
+      rules: {
+        zdshlxmc: [{ required: true, message: '自动审核类型名称必填', trigger: 'blur' }],
+        zdshlxsxl: [{ required: true, message: '自动审核类型实现类必填', trigger: 'blur' }]
+      }
+    }
+  },
+  filters: {
+    statusFilter(status) {
+      const statusMap = {
+        '1': 'success',
+        '0': 'danger'
+      }
+      return statusMap[status]
+    }
+  },
+  created() {
+    this.handlePageList()
+    this.height = window.innerHeight - 216
+  },
+  methods: {
+    handlePageList() {
+      crudPageList(this, getList)
+    },
+    handleCreate(rowid, dialogStatus) {
+      this.dialogStatus = dialogStatus
+      crudGetItem(this, getItem, rowid, initData)
+    },
+    handleReset() {
+      resetForm(this.listQuery)
+    },
+    handleFilter() {
+      this.listQuery.pageIndex = 1
+      this.handlePageList()
+    },
+    handleSizeChange(val) {
+      this.listQuery.pageSize = val
+      this.handlePageList()
+    },
+    handleCurrentChange(val) {
+      this.listQuery.pageIndex = val
+      this.handlePageList()
+    },
+    createData() {
+      crudCreate(this, createRosterSyncInterface, this.handlePageList)
+    },
+    handleDelete(rowid) {
+      crudDelete(this, deleteRosterSyncInterface, rowid, this.handlePageList)
+    }
+  }
+}
+</script>
diff --git a/leave-school-vue/src/views/systemmanagement/schoolyear/index.vue b/leave-school-vue/src/views/systemmanagement/schoolyear/index.vue
new file mode 100644
index 0000000..53c7014
--- /dev/null
+++ b/leave-school-vue/src/views/systemmanagement/schoolyear/index.vue
@@ -0,0 +1,130 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="学年代码" v-model="listQuery.xndm">
+      </el-input>
+      <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="学年名称" v-model="listQuery.xnmc">
+      </el-input>
+      <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">查询</el-button>
+      <el-button class="filter-item" style="margin-left: 10px;" @click="handleCreate(null, 'create')" type="primary" icon="el-icon-edit">添加</el-button>
+      <el-button class="filter-item" style="margin-left: 10px;" @click="handleReset" type="primary" icon="el-icon-edit">重置</el-button>
+    </div>
+    <el-table :height="height" :data="items" v-loading="listLoading" element-loading-text="Loading" border fit highlight-current-row>
+      <el-table-column align="center" label='序号' width="95">
+        <template slot-scope="scope">
+          {{scope.row.id}}
+        </template>
+      </el-table-column>
+      <el-table-column label="学年代码" align="center">
+        <template slot-scope="scope">
+          {{scope.row.xndm}}
+        </template>
+      </el-table-column>
+      <el-table-column label="学年名称" align="center">
+        <template slot-scope="scope">
+          <span>{{scope.row.xnmc}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column
+        header-align="center"
+        align="center"
+        width="150"
+        label="操作">
+        <template slot-scope="scope">
+          <el-button type="text" size="small" @click="handleCreate(scope.row.id, 'update')">修改</el-button>
+          <el-button type="text" size="small" @click="handleDelete(scope.row.id)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <div class="pagination-container">
+      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.pageIndex" 
+      :page-sizes="[10,20,30, 50]" :page-size="listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="recordCount">
+      </el-pagination>
+    </div>
+    
+    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
+      <el-form :rules="rules" ref="dataForm" :model="temp" label-position="left" label-width="150px" style='width: 400px; margin-left:50px;'>
+        <el-form-item label="学年代码1" prop="xndm">
+          <el-input v-if="dialogStatus === 'update'" disabled v-model="temp.xndm"></el-input>
+          <el-input v-else v-model="temp.xndm"></el-input>
+          <input type="hidden" v-model="temp.id" />
+        </el-form-item>
+        <el-form-item label="学年名称" prop="xnmc">
+          <el-input v-model="temp.xnmc"></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogFormVisible = false">返回</el-button>
+        <el-button type="primary" @click="createData">提交</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getList, getItem, createSchoolyear, deleteSchoolyear } from '@/api/schoolyear-api'
+import waves from '@/directive/waves' // 水波纹指令
+import { resetForm } from '@/utils'
+import { crudPageList, crudGetItem, crudCreate, crudDelete } from '@/utils/crud'
+import mixindata from '@/utils/crud'
+
+const initData = {}
+export default {
+  name: 'schoolyear',
+  directives: {
+    waves
+  },
+  mixins: [mixindata],
+  data() {
+    return {
+      rules: {
+        xndm: [{ required: true, message: '学年代码必填', trigger: 'blur' }],
+        xnmc: [{ required: true, message: '学年名称必填', trigger: 'blur' }]
+      }
+    }
+  },
+  filters: {
+    statusFilter(status) {
+      const statusMap = {
+        '1': 'success',
+        '0': 'danger'
+      }
+      return statusMap[status]
+    }
+  },
+  created() {
+    this.handlePageList()
+    this.height = window.innerHeight - 216
+  },
+  methods: {
+    handlePageList() {
+      crudPageList(this, getList)
+    },
+    handleCreate(rowid, dialogStatus) {
+      this.dialogStatus = dialogStatus
+      crudGetItem(this, getItem, rowid, initData)
+    },
+    handleReset() {
+      resetForm(this.listQuery)
+    },
+    handleFilter() {
+      this.listQuery.pageIndex = 1
+      this.handlePageList()
+    },
+    handleSizeChange(val) {
+      this.listQuery.pageSize = val
+      this.handlePageList()
+    },
+    handleCurrentChange(val) {
+      this.listQuery.pageIndex = val
+      this.handlePageList()
+    },
+    createData() {
+      crudCreate(this, createSchoolyear, this.handlePageList)
+    },
+    handleDelete(rowid) {
+      crudDelete(this, deleteSchoolyear, rowid, this.handlePageList)
+    }
+  }
+}
+</script>
\ No newline at end of file
diff --git a/leave-school-vue/src/views/workteam/departmentleader/index.vue b/leave-school-vue/src/views/workteam/departmentleader/index.vue
new file mode 100644
index 0000000..c521dce
--- /dev/null
+++ b/leave-school-vue/src/views/workteam/departmentleader/index.vue
@@ -0,0 +1,234 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <el-row :gutter="20">
+        <el-col :span="4">
+          <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="工号" v-model="listQuery.gh">
+          </el-input>
+        </el-col>
+        <el-col :span="4">
+          <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="姓名" v-model="listQuery.xm">
+          </el-input>
+        </el-col>
+        <el-col :span="4">
+          <el-select clearable class="filter-item" v-model="listQuery.yx" placeholder="院系">
+            <el-option v-for="item in  yxList" :key="item.id" :label="item.dwmc" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="12">
+          <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">查询</el-button>
+          <el-button class="filter-item" style="margin-left: 10px;" @click="handleCreate(null, 'create')" type="primary" icon="el-icon-edit">添加</el-button>
+          <el-button class="filter-item" style="margin-left: 10px;" @click="handleReset" type="primary" icon="el-icon-edit">重置</el-button>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="4">
+          <el-select clearable class="filter-item" v-model="listQuery.zzmm" placeholder="政治面貌">
+            <el-option v-for="item in  zzmmList" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="4">
+          <el-select clearable class="filter-item" v-model="listQuery.xb" placeholder="性别">
+            <el-option v-for="item in  xbList" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="4">
+        </el-col>
+        <el-col :span="12">
+        </el-col>
+      </el-row>
+    </div>
+    <el-table :height="height" :data="items" v-loading="listLoading" element-loading-text="Loading" border fit highlight-current-row>
+      <el-table-column align="center" label='工号'>
+        <template slot-scope="scope">
+          {{scope.row.gh}}
+        </template>
+      </el-table-column>
+      <el-table-column label="姓名" align="center">
+        <template slot-scope="scope">
+          {{scope.row.xm}}
+        </template>
+      </el-table-column>
+      <el-table-column label="院系" align="center">
+        <template slot-scope="scope">
+          <span>{{scope.row.yx}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="性别" align="center">
+        <template slot-scope="scope">
+          {{scope.row.xb}}
+        </template>
+      </el-table-column>
+      <el-table-column label="政治面貌" align="center">
+        <template slot-scope="scope">
+          {{scope.row.zzmm}}
+        </template>
+      </el-table-column>
+      <el-table-column label="联系电话" align="center">
+        <template slot-scope="scope">
+          {{scope.row.lxdh}}
+        </template>
+      </el-table-column>
+      <el-table-column label="是否在任" align="center">
+        <template slot-scope="scope">
+          {{scope.row.sfzr}}
+        </template>
+      </el-table-column>
+      <el-table-column
+        fixed="right"
+        header-align="center"
+        align="center"
+        width="150"
+        label="操作">
+        <template slot-scope="scope">
+          <el-button type="text" size="small" @click="handleCreate(scope.row.id, 'update')">修改</el-button>
+          <el-button type="text" size="small" @click="handleDelete(scope.row.id)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <div class="pagination-container">
+      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.pageIndex" :page-sizes="[10,20,30, 50]" :page-size="listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="recordCount">
+      </el-pagination>
+    </div>
+
+    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
+      <el-form :rules="rules" ref="dataForm" :model="temp" label-position="left" label-width="150px" style='width: 400px; margin-left:50px;'>
+        <el-form-item label="工号" prop="gh">
+          <el-input v-model="temp.gh"></el-input>
+          <input type="hidden" v-model="temp.id" />
+        </el-form-item>
+        <el-form-item label="姓名" prop="xm">
+          <el-input v-model="temp.xm"></el-input>
+        </el-form-item>
+        <el-form-item label="性别">
+          <el-select class="filter-item" v-model="temp.xb" placeholder="请选择">
+            <el-option v-for="item in  xbList" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="政治面貌">
+          <el-select class="filter-item" v-model="temp.zzmm" placeholder="请选择">
+            <el-option v-for="item in  zzmmList" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="联系电话" prop="lxdh">
+          <el-input v-model="temp.lxdh"></el-input>
+        </el-form-item>
+        <el-form-item label="是否在任">
+          <el-select class="filter-item" v-model="temp.sfzr" placeholder="请选择">
+            <el-option key="1" label="是" value="1">
+            </el-option>
+            <el-option key="0" label="否" value="0">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="院系" prop="yx">
+          <el-select class="filter-item" v-model="temp.yx" placeholder="--请选择院系--">
+            <el-option v-for="item in  yxList" :key="item.id" :label="item.dwmc" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogFormVisible = false">返回</el-button>
+        <el-button type="primary" @click="createData">提交</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getList, getItem, createDepartmentleader, deleteDepartmentleader } from '@/api/departmentleader-api'
+import { getDicList } from '@/api/dictionary-api'
+import { getAllList as getAllDeptList } from '@/api/department-api'
+import waves from '@/directive/waves' // 水波纹指令
+import { resetForm } from '@/utils'
+import { crudPageList, crudGetItem, crudCreate, crudDelete } from '@/utils/crud'
+import mixindata from '@/utils/crud'
+
+const initData = { sfky: '1' }
+export default {
+  name: 'departmentleader',
+  directives: {
+    waves
+  },
+  mixins: [mixindata],
+  data() {
+    return {
+      yxList: [],
+      zzmmList: [],
+      xbList: [],
+      rules: {
+        gh: [{ required: true, message: '工号必填', trigger: 'blur' }],
+        xm: [{ required: true, message: '姓名必填', trigger: 'blur' }],
+        yx: [{ required: true, message: '院系必填', trigger: 'change' }]
+      }
+    }
+  },
+  filters: {
+    statusFilter(status) {
+      const statusMap = {
+        '1': 'success',
+        '0': 'danger'
+      }
+      return statusMap[status]
+    }
+  },
+  created() {
+    this.getYxList()
+    this.getZzmmList()
+    this.getXbList()
+    this.handlePageList()
+    this.height = window.innerHeight - 266
+  },
+  methods: {
+    getYxList() {
+      getAllDeptList(this.listQuery).then(response => {
+        this.yxList = response.items
+      })
+    },
+    getZzmmList() {
+      getDicList({ type: 'zzmm' }).then(response => {
+        this.zzmmList = response.items
+      })
+    },
+    getXbList() {
+      getDicList({ type: 'xb' }).then(response => {
+        this.xbList = response.items
+      })
+    },
+    handlePageList() {
+      crudPageList(this, getList)
+    },
+    handleCreate(rowid, dialogStatus) {
+      this.dialogStatus = dialogStatus
+      crudGetItem(this, getItem, rowid, initData)
+    },
+    handleReset() {
+      resetForm(this.listQuery)
+    },
+    handleFilter() {
+      this.listQuery.pageIndex = 1
+      this.handlePageList()
+    },
+    handleSizeChange(val) {
+      this.listQuery.pageSize = val
+      this.handlePageList()
+    },
+    handleCurrentChange(val) {
+      this.listQuery.pageIndex = val
+      this.handlePageList()
+    },
+    createData() {
+      crudCreate(this, createDepartmentleader, this.handlePageList)
+    },
+    handleDelete(rowid) {
+      crudDelete(this, deleteDepartmentleader, rowid, this.handlePageList)
+    }
+  }
+}
+</script>
diff --git a/leave-school-vue/src/views/workteam/instructor/index.vue b/leave-school-vue/src/views/workteam/instructor/index.vue
new file mode 100644
index 0000000..cad431e
--- /dev/null
+++ b/leave-school-vue/src/views/workteam/instructor/index.vue
@@ -0,0 +1,223 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <el-row :gutter="20">
+        <el-col :span="4">
+          <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="工号" v-model="listQuery.gh">
+          </el-input>
+        </el-col>
+        <el-col :span="4">
+          <el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="姓名" v-model="listQuery.xm">
+          </el-input>
+        </el-col>
+        <el-col :span="4">
+          <el-select clearable class="filter-item" v-model="listQuery.yx" placeholder="院系">
+            <el-option v-for="item in  szyxList" :key="item.id" :label="item.dwmc" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="12">
+          <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">查询</el-button>
+          <el-button class="filter-item" style="margin-left: 10px;" @click="handleCreate(null, 'create')" type="primary" icon="el-icon-edit">添加</el-button>
+          <el-button class="filter-item" style="margin-left: 10px;" @click="handleReset" type="primary" icon="el-icon-edit">重置</el-button>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="4">
+          <el-select clearable class="filter-item" v-model="listQuery.zzmm" placeholder="政治面貌">
+            <el-option v-for="item in  zzmmList" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="4">
+          <el-select clearable class="filter-item" v-model="listQuery.sfzr" placeholder="是否在任">
+            <el-option key="1" label="是" value="1">
+            </el-option>
+            <el-option key="0" label="否" value="0">
+            </el-option>
+          </el-select>
+        </el-col>
+        <el-col :span="4">
+        </el-col>
+        <el-col :span="12">
+        </el-col>
+      </el-row>
+    </div>
+    <el-table :height="height" :data="items" v-loading="listLoading" element-loading-text="Loading" border fit highlight-current-row>
+      <el-table-column align="center" label='工号'>
+        <template slot-scope="scope">
+          {{scope.row.gh}}
+        </template>
+      </el-table-column>
+      <el-table-column label="姓名" align="center">
+        <template slot-scope="scope">
+          {{scope.row.xm}}
+        </template>
+      </el-table-column>
+      <el-table-column label="所带班级" align="center">
+        <template slot-scope="scope">
+          <span>{{scope.row.sdbj}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="班级总人数" align="center">
+        <template slot-scope="scope">
+          {{scope.row.bjzrs}}
+        </template>
+      </el-table-column>
+      <el-table-column label="所在院系" align="center">
+        <template slot-scope="scope">
+          {{scope.row.szyx}}
+        </template>
+      </el-table-column>
+      <el-table-column label="是否在任" align="center">
+        <template slot-scope="scope">
+          {{scope.row.sfzr}}
+        </template>
+      </el-table-column>
+      <el-table-column
+        fixed="right"
+        header-align="center"
+        align="center"
+        width="150"
+        label="操作">
+        <template slot-scope="scope">
+          <el-button type="text" size="small" @click="handleCreate(scope.row.id, 'update')">修改</el-button>
+          <el-button type="text" size="small" @click="handleDelete(scope.row.id)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <div class="pagination-container">
+      <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.pageIndex" :page-sizes="[10,20,30, 50]" :page-size="listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="recordCount">
+      </el-pagination>
+    </div>
+
+    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
+      <el-form :rules="rules" ref="dataForm" :model="temp" label-position="left" label-width="150px" style='width: 400px; margin-left:50px;'>
+        <el-form-item label="工号" prop="gh">
+          <el-input v-model="temp.gh"></el-input>
+          <input type="hidden" v-model="temp.id" />
+        </el-form-item>
+        <el-form-item label="姓名" prop="xm">
+          <el-input v-model="temp.xm"></el-input>
+        </el-form-item>
+        <el-form-item label="所带班级" prop="sdbj">
+          <el-select class="filter-item" v-model="temp.sdbj" placeholder="请选择">
+            <el-option v-for="item in  sdbjList" :key="item.id" :label="item.bjmc" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="是否在任">
+          <el-select class="filter-item" v-model="temp.sfzr" placeholder="请选择">
+            <el-option key="1" label="是" value="1">
+            </el-option>
+            <el-option key="0" label="否" value="0">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="所在院系">
+          <el-select class="filter-item" v-model="temp.szyx" placeholder="--请选择院系--">
+            <el-option v-for="item in  szyxList" :key="item.id" :label="item.dwmc" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogFormVisible = false">返回</el-button>
+        <el-button type="primary" @click="createData">提交</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getList, getItem, createInstructor, deleteInstructor } from '@/api/instructor-api'
+import { getAllList } from '@/api/class-api'
+import { getDicList } from '@/api/dictionary-api'
+import { getAllList as getAllDeptList } from '@/api/department-api'
+import waves from '@/directive/waves' // 水波纹指令
+import { resetForm } from '@/utils'
+import { crudPageList, crudGetItem, crudCreate, crudDelete } from '@/utils/crud'
+import mixindata from '@/utils/crud'
+
+const initData = { sfky: '1' }
+export default {
+  name: 'instructor',
+  directives: {
+    waves
+  },
+  mixins: [mixindata],
+  data() {
+    return {
+      szyxList: [],
+      sdbjList: [],
+      zzmmList: [],
+      rules: {
+        gh: [{ required: true, message: '工号必填', trigger: 'blur' }],
+        xm: [{ required: true, message: '姓名必填', trigger: 'blur' }],
+        sdbj: [{ required: true, message: '所带班级必填', trigger: 'change' }]
+      }
+    }
+  },
+  filters: {
+    statusFilter(status) {
+      const statusMap = {
+        '1': 'success',
+        '0': 'danger'
+      }
+      return statusMap[status]
+    }
+  },
+  created() {
+    this.getSzyxList()
+    this.getSdbjList()
+    this.getZzmmList()
+    this.handlePageList()
+    this.height = window.innerHeight - 266
+  },
+  methods: {
+    getSzyxList() {
+      getAllDeptList(this.listQuery).then(response => {
+        this.szyxList = response.items
+      })
+    },
+    getSdbjList() {
+      getAllList(this.listQuery).then(response => {
+        this.sdbjList = response.items
+      })
+    },
+    getZzmmList() {
+      getDicList({ type: 'zzmm' }).then(response => {
+        this.zzmmList = response.items
+      })
+    },
+    handlePageList() {
+      crudPageList(this, getList)
+    },
+    handleCreate(rowid, dialogStatus) {
+      this.dialogStatus = dialogStatus
+      crudGetItem(this, getItem, rowid, initData)
+    },
+    handleReset() {
+      resetForm(this.listQuery)
+    },
+    handleFilter() {
+      this.listQuery.pageIndex = 1
+      this.handlePageList()
+    },
+    handleSizeChange(val) {
+      this.listQuery.pageSize = val
+      this.handlePageList()
+    },
+    handleCurrentChange(val) {
+      this.listQuery.pageIndex = val
+      this.handlePageList()
+    },
+    createData() {
+      crudCreate(this, createInstructor, this.handlePageList)
+    },
+    handleDelete(rowid) {
+      crudDelete(this, deleteInstructor, rowid, this.handlePageList)
+    }
+  }
+}
+</script>