dusenyao 3 år sedan
förälder
incheckning
7898499f23

+ 1 - 1
.eslintrc.js

@@ -34,7 +34,7 @@ module.exports = {
         endOfLine: 'auto',
         bracketSpacing: true,
         arrowParens: 'avoid',
-        printWidth: 100
+        printWidth: 120
       }
     ],
     'vue/max-attributes-per-line': [

+ 2 - 10
.vscode/launch.json

@@ -5,10 +5,10 @@
   "version": "0.2.0",
   "configurations": [
     {
-      "type": "chrome",
+      "type": "pwa-chrome",
       "request": "launch",
       "name": "vuejs: chrome",
-      "url": "http://localhost:7979",
+      "url": "http://localhost:7878",
       "webRoot": "${workspaceFolder}/src",
       "breakOnLoad": true,
       "sourceMapPathOverrides": {
@@ -16,14 +16,6 @@
         "webpack:///src/*": "${webRoot}/*",
         "webpack:///./src/*.js": "${webRoot}/*.js"
       }
-    },
-    {
-      "type": "firefox",
-      "request": "launch",
-      "name": "vuejs: firefox",
-      "url": "http://localhost:7979",
-      "webRoot": "${workspaceFolder}/src",
-      "pathMappings": [{ "url": "webpack:///src/", "path": "${webRoot}/" }]
     }
   ]
 }

+ 1 - 0
.vscode/settings.json

@@ -0,0 +1 @@
+{}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 22662 - 1
package-lock.json


+ 13 - 12
package.json

@@ -9,9 +9,9 @@
     "lint": "eslint --ext .js,.vue src"
   },
   "dependencies": {
-    "axios": "^0.21.1",
-    "core-js": "^3.12.1",
-    "element-ui": "^2.15.1",
+    "axios": "^0.21.4",
+    "core-js": "^3.17.2",
+    "element-ui": "^2.15.6",
     "js-cookie": "^2.2.1",
     "normalize.css": "^8.0.1",
     "nprogress": "^0.2.0",
@@ -35,22 +35,23 @@
     "babel-loader": "^8.2.2",
     "babel-plugin-dynamic-import-node": "^2.3.3",
     "eslint": "^7.26.0",
-    "eslint-plugin-prettier": "^3.4.0",
+    "eslint-plugin-prettier": "^3.4.1",
     "eslint-plugin-vue": "^7.9.0",
     "html-webpack-plugin": "^5.3.1",
     "node-sass": "^5.0.0",
-    "prettier": "2.3.0",
+    "prettier": "2.3.2",
     "sass": "^1.32.13",
-    "sass-loader": "^10.1.1",
+    "sass-loader": "^10.2.0",
     "script-ext-html-webpack-plugin": "^2.1.5",
     "stylelint": "^13.13.1",
+    "stylelint-config-recess-order": "^2.5.0",
+    "stylelint-config-sass-guidelines": "^8.0.0",
     "stylelint-config-standard": "^22.0.0",
-    "stylelint-declaration-block-no-ignored-properties": "^2.3.0",
-    "stylelint-order": "^4.1.0",
-    "stylelint-scss": "^3.19.0",
-    "stylelint-webpack-plugin": "^2.1.1",
-    "svg-sprite-loader": "^6.0.6",
-    "svgo": "^2.3.0",
+    "stylelint-declaration-block-no-ignored-properties": "^2.4.0",
+    "stylelint-scss": "^3.20.1",
+    "stylelint-webpack-plugin": "^2.2.2",
+    "svg-sprite-loader": "^6.0.9",
+    "svgo": "^2.5.0",
     "vue-loader": "^15.9.7",
     "vue-template-compiler": "^2.6.12"
   },

+ 27 - 1
src/api/app.js

@@ -1,4 +1,4 @@
-import { request } from '@/utils/request';
+import { request, getRequestParameter } from '@/utils/request';
 import { getUserInfo } from '@/utils/auth';
 
 /**
@@ -27,3 +27,29 @@ export function fileUpload(SecurityLevel, file) {
     data: formData
   });
 }
+
+/**
+ * 得到系统标志
+ */
+export function GetLogo() {
+  let params = getRequestParameter('sys_config_manager-GetLogo');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_FileServer,
+    params
+  });
+}
+
+/**
+ * 得到用户能进入的子系统列表(电脑端)
+ */
+export function GetChildSysList_CanEnter_PC() {
+  let params = getRequestParameter('login_control-GetChildSysList_CanEnter_PC');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_FileServer,
+    params
+  });
+}

+ 30 - 0
src/api/org.js

@@ -29,3 +29,33 @@ export function GetOrgList_User(data) {
     data
   });
 }
+
+/**
+ * 得到机构信息
+ * @param {Object} data { ID 结构ID }
+ */
+export function GetOrgInfo(data) {
+  let params = getRequestParameter('org_manager-GetOrgInfo');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_FileServer,
+    params,
+    data
+  });
+}
+
+/**
+ * 修改机构
+ * @param {Object} data
+ */
+export function UpdateOrg(data) {
+  let params = getRequestParameter('org_manager-UpdateOrg');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_FileServer,
+    params,
+    data
+  });
+}

+ 31 - 1
src/api/user.js

@@ -1,4 +1,4 @@
-import { request } from '@/utils/request';
+import { request, getRequestParameter } from '@/utils/request';
 
 /**
  * 登录
@@ -11,3 +11,33 @@ export function login(data) {
     data
   });
 }
+
+/**
+ * 修改密码
+ * @param {Object} data { password_old 旧密码 password_new 新密码 }
+ */
+export function UpdateMyPassword(data) {
+  let params = getRequestParameter('user_manager-UpdateMyPassword');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_FileServer,
+    params,
+    data
+  });
+}
+
+/**
+ * .重置机构管理员密码
+ * @param {Object} data { user_id 用户ID password 密码 }
+ */
+export function ResetOrgAdminPassword(data) {
+  let params = getRequestParameter('user_manager-ResetOrgAdminPassword');
+
+  return request({
+    method: 'post',
+    url: process.env.VUE_APP_FileServer,
+    params,
+    data
+  });
+}

+ 92 - 0
src/components/ResetPassword.vue

@@ -0,0 +1,92 @@
+<template>
+  <el-dialog
+    class="reset-password"
+    :visible="visible"
+    :before-close="close"
+    title="重置密码"
+    width="500px"
+    :destroy-on-close="true"
+  >
+    <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+      <el-form-item label="新密码" prop="password">
+        <el-input v-model="form.password" autocomplete="off" type="password" />
+      </el-form-item>
+
+      <el-form-item label="确认密码" prop="password_confrim">
+        <el-input v-model="form.password_confrim" autocomplete="off" type="password" />
+      </el-form-item>
+    </el-form>
+
+    <footer slot="footer">
+      <el-button type="primary" @click="resetOrgAdminPassword">确定</el-button>
+    </footer>
+  </el-dialog>
+</template>
+
+<script>
+import { ResetOrgAdminPassword } from '@/api/user';
+
+export default {
+  props: {
+    userId: {
+      default: '',
+      type: String
+    }
+  },
+  data() {
+    const validateConfirm = (rule, value, callback) => {
+      if (value !== this.form.password) {
+        callback(new Error('新密码与确认密码不一致'));
+      } else {
+        callback();
+      }
+    };
+
+    return {
+      visible: false,
+      form: {
+        password: '',
+        password_confrim: ''
+      },
+      rules: {
+        password: [{ required: true, message: '请输入新密码' }],
+        password_confrim: [
+          { required: true, message: '请输入确认密码' },
+          { required: true, validator: validateConfirm }
+        ]
+      }
+    };
+  },
+  methods: {
+    resetOrgAdminPassword() {
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          ResetOrgAdminPassword({ user_id: this.userId, password: this.form.password }).then(() => {
+            this.$message.success('重置密码成功');
+            this.visible = false;
+          });
+        } else {
+          return false;
+        }
+      });
+    },
+
+    show() {
+      this.visible = true;
+    },
+
+    close() {
+      this.$refs.form.resetFields();
+      this.visible = false;
+    }
+  }
+};
+</script>
+
+<style lang="scss">
+.reset-password {
+  .el-dialog__body {
+    padding-bottom: 0;
+  }
+}
+</style>

+ 38 - 21
src/layouts/components/LayoutHeader.vue

@@ -2,9 +2,10 @@
   <div class="header">
     <div class="header-top">
       <el-row type="flex" justify="space-between">
-        <el-col :span="4" class="header-top-logo">LOGO</el-col>
+        <el-col :span="4" class="header-top-logo">
+          <el-image :src="$store.state.app.config.logo_image_url" />
+        </el-col>
         <el-col class="header-top-tab" :span="16">
-          <span>主页</span>
           <template v-for="item in routerList">
             <router-link v-if="item.isShow" :key="item.path" :to="item.path">
               {{ item.name }}
@@ -16,33 +17,37 @@
           <el-dropdown class="header-top-user-name" placement="bottom">
             <span>{{ realName }}</span>
             <el-dropdown-menu slot="dropdown">
+              <el-dropdown-item @click.native="updateMyPassword">修改密码</el-dropdown-item>
               <el-dropdown-item @click.native="signOut">退出</el-dropdown-item>
             </el-dropdown-menu>
           </el-dropdown>
-          <el-badge :is-dot="isDot" class="header-top-user-bell">
-            <i class="el-icon-bell"></i>
-          </el-badge>
         </el-col>
       </el-row>
     </div>
     <div class="header-crumbs">
       <div class="header-crumbs-navigation">
-        <span class="home-page">后台主页 ></span>
-        <router-link v-for="item in levelList" :key="item.path" :to="item.path">
-          {{ item.meta.title }}
+        <router-link v-for="(item, i) in levelList" :key="i" :to="item.meta.path ? item.meta.path : ''">
+          <i v-show="i > 0" class="el-icon-arrow-right" /> {{ item.meta.title }}
         </router-link>
       </div>
     </div>
+
+    <update-password ref="password" />
   </div>
 </template>
 
 <script>
+import UpdatePassword from './UpdatePassword.vue';
+import { GetChildSysList_CanEnter_PC } from '@/api/app';
+
 export default {
   name: 'LayoutHeader',
+  components: {
+    UpdatePassword
+  },
   data() {
     return {
-      levelList: null,
-      isDot: false
+      levelList: null
     };
   },
   computed: {
@@ -99,11 +104,19 @@ export default {
   },
   created() {
     this.getBreadcrumb();
+    GetChildSysList_CanEnter_PC().then(({ child_sys_list }) => {
+      if (child_sys_list && child_sys_list.length > 0) {
+        console.log(child_sys_list);
+      }
+    });
   },
   methods: {
     getBreadcrumb() {
       this.levelList = this.$route.matched.filter(item => item.meta && item.meta.title);
     },
+    updateMyPassword() {
+      this.$refs.password.show();
+    },
     async signOut() {
       await this.$store.dispatch('user/signOut');
       this.$router.push(`/login`);
@@ -114,12 +127,12 @@ export default {
 
 <style lang="scss">
 .header {
-  width: 100%;
-  min-width: 1200px;
   position: fixed;
   top: 0;
   left: 0;
   z-index: 9;
+  width: 100%;
+  min-width: 1200px;
 
   // 顶部
   &-top {
@@ -129,22 +142,26 @@ export default {
     background-color: #fff;
 
     &-logo {
-      font-size: 30px;
-      font-weight: 700;
-      padding-right: 20px;
+      margin-top: -15px;
     }
 
     &-tab {
       a {
         margin-left: 24px;
+        font-weight: bold;
       }
     }
 
     &-user {
       &-name {
-        vertical-align: top;
         margin-left: 8px;
+        font-weight: bold;
+        vertical-align: top;
         cursor: pointer;
+
+        > span {
+          font-size: 18px;
+        }
       }
 
       & > &-bell {
@@ -162,29 +179,29 @@ export default {
 
     &-navigation {
       width: 1200px;
-      height: 100%;
       min-width: 1200px;
-      margin: 0 auto;
+      height: 100%;
       padding: 15px 0;
+      margin: 0 auto;
       font-size: 18px;
       font-weight: 700;
       line-height: 26px;
       vertical-align: middle;
 
       &::before {
-        content: '';
         display: inline-block;
         width: 6px;
         height: 100%;
-        vertical-align: bottom;
         margin-right: 24px;
+        vertical-align: bottom;
+        content: '';
         background-color: #0085ff;
       }
 
       .home-page {
         color: #848b91;
 
-        & ~ a {
+        ~ a {
           margin-left: 8px;
         }
       }

+ 96 - 0
src/layouts/components/UpdatePassword.vue

@@ -0,0 +1,96 @@
+<template>
+  <el-dialog
+    title="修改密码"
+    :visible="visible"
+    :modal="false"
+    :before-close="close"
+    width="600px"
+    :close-on-click-modal="false"
+  >
+    <el-form ref="form" :model="passwordForm" :rules="rules" label-width="80px">
+      <el-form-item label="旧密码">
+        <el-input v-model="passwordForm.password_old" autocomplete="off" />
+      </el-form-item>
+      <el-form-item label="新密码" prop="password_new">
+        <el-input v-model="passwordForm.password_new" autocomplete="off" type="password" />
+      </el-form-item>
+      <el-form-item label="确认密码" prop="password_confirm">
+        <el-input v-model="passwordForm.password_confirm" autocomplete="off" type="password" />
+      </el-form-item>
+    </el-form>
+
+    <footer slot="footer">
+      <el-button type="primary" @click="updateMyPassword">确定</el-button>
+      <el-button @click="close">关闭</el-button>
+    </footer>
+  </el-dialog>
+</template>
+
+<script>
+import { UpdateMyPassword } from '@/api/user';
+
+export default {
+  data() {
+    const confirmPassword = (rule, value, callback) => {
+      if (this.passwordForm.password_new !== value) {
+        callback(new Error('新密码与确认密码不一致'));
+      } else {
+        callback();
+      }
+    };
+
+    return {
+      visible: false,
+      passwordForm: {
+        password_old: '',
+        password_new: '',
+        password_confirm: ''
+      },
+      rules: {
+        password_new: [{ required: true, message: '请输入新密码', trigger: 'blur' }],
+        password_confirm: [
+          { required: true, message: '请输入确认密码', trigger: 'blur' },
+          { validator: confirmPassword, trigger: 'blur' }
+        ]
+      }
+    };
+  },
+  methods: {
+    updateMyPassword() {
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          UpdateMyPassword({
+            password_old: this.passwordForm.password_old,
+            password_new: this.passwordForm.password_new
+          }).then(() => {
+            this.visible = false;
+            this.signOut();
+          });
+        } else {
+          return false;
+        }
+      });
+    },
+
+    async signOut() {
+      await this.$store.dispatch('user/signOut');
+      this.$router.push(`/login`);
+      this.$message.success('修改密码成功,请重新登录');
+    },
+
+    show() {
+      this.visible = true;
+    },
+
+    close() {
+      this.visible = false;
+    }
+  }
+};
+</script>
+
+<style lang="scss">
+@import '~@/styles/mixin';
+
+@include dialog;
+</style>

+ 3 - 4
src/permission.js

@@ -1,9 +1,8 @@
 import router from './router';
-import { getSessionID } from '@/utils/auth';
+import { getSessionID, getConfig } from '@/utils/auth';
 
 import NProgress from 'nprogress';
 import 'nprogress/nprogress.css';
-
 NProgress.configure({ showSpinner: false });
 
 const whiteList = ['/login']; // 重定向白名单
@@ -12,8 +11,8 @@ const whiteList = ['/login']; // 重定向白名单
 router.beforeEach(async (to, from, next) => {
   NProgress.start();
 
-  const session_id = getSessionID();
-  if (session_id) {
+  const { isHas } = getConfig();
+  if (getSessionID() && isHas) {
     if (to.path === '/login') {
       next({ path: '/' });
       NProgress.done();

+ 2 - 1
src/router/index.js

@@ -57,7 +57,7 @@ const routes = [
     path: '/',
     component: Layout,
     redirect: { name: 'OrgManager' },
-    meta: { title: '机构管理' },
+    meta: { title: '机构管理', path: '/org_manager' },
     children: [
       {
         path: '/org_manager',
@@ -69,6 +69,7 @@ const routes = [
       },
       {
         path: '/add_org',
+        meta: { title: '创建机构' },
         component: () => import('@/views/org_manager/AddOrg'),
         beforeEnter: (to, form, next) => {
           beforeRouterPopedom(1000001, next);

+ 2 - 0
src/store/index.js

@@ -1,6 +1,7 @@
 import Vue from 'vue';
 import Vuex from 'vuex';
 import getters from './getters';
+import app from './modules/app';
 import user from './modules/user';
 
 Vue.use(Vuex);
@@ -10,6 +11,7 @@ export default new Vuex.Store({
   mutations: {},
   actions: {},
   modules: {
+    app,
     user
   },
   getters,

+ 29 - 0
src/store/modules/app.js

@@ -0,0 +1,29 @@
+import { getConfig } from '@/utils/auth';
+
+const getDefaultSate = () => {
+  const { isHas, token } = getConfig();
+
+  if (isHas) document.title = token.title;
+
+  return {
+    config: {
+      title: isHas ? token.title : '',
+      logo_image_url: isHas ? token.logo_image_url : '',
+      logo_image_url_home: isHas ? token.logo_image_url_home : '',
+      sys_type: isHas ? token.sys_type : ''
+    }
+  };
+};
+
+const state = getDefaultSate();
+
+const mutations = {};
+
+const actions = {};
+
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions
+};

+ 10 - 0
src/styles/element-ui.scss

@@ -0,0 +1,10 @@
+.el-button.el-button--primary {
+  color: #fff;
+  background-color: $basic-color;
+  border-color: $basic-color;
+
+  &:hover {
+    color: #efefef;
+    background-color: #f19100;
+  }
+}

+ 14 - 16
src/styles/index.scss

@@ -1,24 +1,23 @@
-@import './variables.scss';
-@import './mixin.scss';
+@import './variables';
+@import './mixin';
+@import './element-ui';
 
 body {
   height: 100%;
+  overflow: hidden;
+  font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Arial', sans-serif;
   -moz-osx-font-smoothing: grayscale;
   -webkit-font-smoothing: antialiased;
   text-rendering: optimizeLegibility;
-  overflow: hidden;
-  /* stylelint-disable-next-line */
-  font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial,
-    sans-serif;
 }
 
 label {
-  font-weight: 700;
+  font-weight: bold;
 }
 
 html {
-  height: 100%;
   box-sizing: border-box;
+  height: 100%;
 }
 
 #app {
@@ -31,18 +30,17 @@ html {
   box-sizing: inherit;
 }
 
-a:focus,
-a:active {
-  outline: none;
-}
-
-/* stylelint-disable-next-line no-descending-specificity */
 a,
 a:focus,
 a:hover {
-  cursor: pointer;
   color: inherit;
   text-decoration: none;
+  cursor: pointer;
+}
+
+a:focus,
+a:active {
+  outline: none;
 }
 
 div:focus {
@@ -51,8 +49,8 @@ div:focus {
 
 .container {
   width: 1000px;
-  margin: 0 auto;
   height: 100%;
+  margin: 0 auto;
 }
 
 .t-right {

+ 19 - 4
src/styles/mixin.scss

@@ -6,23 +6,23 @@
 }
 
 @mixin el-tag {
-  background-color: #e0e0e0;
+  padding: 0 20px;
   color: #000;
+  background-color: #e0e0e0;
   border-radius: 20px;
-  padding: 0 20px;
 }
 
 @mixin list {
   width: 100%;
   min-height: 594px;
-  border-radius: 8px;
   margin-top: 24px;
   background-color: #fff;
+  border-radius: 8px;
 
   &-title {
     height: 78px;
-    line-height: 78px;
     padding: 0 30px;
+    line-height: 78px;
     border-bottom: 1px solid #d9d9d9;
   }
 
@@ -48,3 +48,18 @@
     }
   }
 }
+
+@mixin dialog {
+  .el-dialog {
+    &__title {
+      font-weight: 700;
+    }
+
+    &__body {
+      max-height: 80vh;
+      padding: 15px 20px 0;
+      overflow: auto;
+      color: #2c2c2c;
+    }
+  }
+}

+ 3 - 2
src/styles/variables.scss

@@ -1,3 +1,4 @@
 $header-h: 49px;
-$bacColor: #c4c4c4;
-$borderColor: #999;
+$bac-color: #c4c4c4;
+$basic-color: #f90;
+$border-color: #999;

+ 18 - 1
src/utils/auth.js

@@ -1,5 +1,4 @@
 import Cookies from 'js-cookie';
-// import qs from 'qs';
 
 const userInfoList = [
   'user_code',
@@ -11,6 +10,7 @@ const userInfoList = [
   'image_url',
   'is_inner'
 ];
+const ConfigKey = 'Manager_Config';
 
 export function getUserInfo() {
   let userInfo = {};
@@ -47,3 +47,20 @@ export function removeSessionID() {
     Cookies.remove(key);
   }
 }
+
+// 系统信息
+export function getConfig() {
+  const token = Cookies.get(ConfigKey);
+  if (token) {
+    return { token: JSON.parse(token), isHas: true };
+  }
+  return { token: {}, isHas: false };
+}
+
+export function setConfig(val) {
+  return Cookies.set(ConfigKey, val);
+}
+
+export function removeConfig() {
+  return Cookies.remove(ConfigKey);
+}

+ 9 - 7
src/views/account_manager/OrgList.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-dialog :visible="visible" :before-close="handleClose">
+  <el-dialog class="org-list" :visible="visible" :before-close="handleClose">
     <div slot="title">用户【{{ curUserName }}】加入的机构列表</div>
 
     <el-table :data="org_list" height="320px" border>
@@ -62,13 +62,15 @@ export default {
 </script>
 
 <style lang="scss">
-.el-table__header {
-  .cell {
-    text-align: center;
+.org-list {
+  .el-table__header {
+    .cell {
+      text-align: center;
+    }
   }
-}
 
-.el-dialog__body {
-  padding-bottom: 0;
+  .el-dialog__body {
+    padding-bottom: 0;
+  }
 }
 </style>

+ 6 - 35
src/views/account_manager/index.vue

@@ -16,26 +16,12 @@
             ></el-option>
           </el-select>
           <span class="search-name">用户名</span>
-          <el-input
-            v-model="user_name"
-            class="account-search"
-            type="text"
-            @keyup.enter.native="queryAccountList"
-          />
+          <el-input v-model="user_name" class="account-search" type="text" @keyup.enter.native="queryAccountList" />
           <span class="search-name">姓名</span>
-          <el-input
-            v-model="real_name"
-            class="account-search"
-            type="text"
-            @keyup.enter.native="queryAccountList"
-          />
+          <el-input v-model="real_name" class="account-search" type="text" @keyup.enter.native="queryAccountList" />
         </el-col>
         <el-col :span="2">
-          <el-button
-            class="search-button"
-            icon="el-icon-search"
-            @click="queryAccountList"
-          ></el-button>
+          <el-button class="search-button" icon="el-icon-search" @click="queryAccountList"></el-button>
         </el-col>
       </el-row>
     </div>
@@ -57,17 +43,6 @@
         </el-table-column>
         <el-table-column prop="phone" label="手机号" width="150" />
         <el-table-column prop="email" label="邮箱" />
-        <el-table-column fixed="right" width="80">
-          <template slot-scope="scope">
-            <el-row type="flex" justify="space-between">
-              <el-col>
-                <el-link :underline="false" @click="handleShow(scope.$index, scope.row)">
-                  查看
-                </el-link>
-              </el-col>
-            </el-row>
-          </template>
-        </el-table-column>
       </el-table>
     </div>
     <el-pagination
@@ -83,12 +58,7 @@
       @size-change="changePageSize"
     />
 
-    <org-list
-      ref="orgList"
-      :user-id="userId"
-      :cur-user-name="curUserName"
-      @orgListClose="orgListClose"
-    />
+    <org-list ref="orgList" :user-id="userId" :cur-user-name="curUserName" @orgListClose="orgListClose" />
   </div>
 </template>
 
@@ -174,7 +144,7 @@ export default {
 </script>
 
 <style lang="scss">
-@import '~@/styles/mixin.scss';
+@import '~@/styles/mixin';
 
 .account-manager {
   @include container;
@@ -216,6 +186,7 @@ export default {
     }
 
     .link {
+      color: #409eff;
       cursor: pointer;
     }
   }

+ 40 - 20
src/views/login/index.vue

@@ -1,7 +1,9 @@
 <template>
   <div class="login">
-    <div class="login-container">
-      <div class="login-container-logo"></div>
+    <main class="login-container">
+      <div class="login-container-logo">
+        <el-image :src="$store.state.app.config.logo_image_url_home"></el-image>
+      </div>
       <div class="login-container-title">欢迎使用全球汉语教学平台后台管理系统</div>
       <div class="login-container-admin">
         <div class="login-container-admin-title">管理员登录</div>
@@ -18,7 +20,7 @@
               type="text"
               prefix-icon="el-icon-user"
               placeholder="邮箱账号"
-            ></el-input>
+            />
           </el-form-item>
 
           <el-form-item prop="password">
@@ -29,13 +31,13 @@
               prefix-icon="el-icon-key"
               placeholder="密码"
               @keyup.enter.native="handleLogin"
-            ></el-input>
+            />
           </el-form-item>
 
           <el-form-item class="form-remember">
             <el-row type="flex" justify="space-between">
               <el-col> <el-checkbox v-model="isRemember" /> 记住我</el-col>
-              <el-col class="forget-password">忘记密码?</el-col>
+              <!-- <el-col class="forget-password">忘记密码?</el-col> -->
             </el-row>
           </el-form-item>
 
@@ -51,18 +53,24 @@
           </el-form-item>
 
           <el-form-item>
-            <el-checkbox v-model="isAgree" />
-            <span> 我已阅读并同意</span>
-            <span style="color: #f90">用户协议</span>
+            <label class="">
+              <el-checkbox v-model="isAgree" />
+              <span> 我已阅读并同意</span>
+              <span class="user-agreement">用户协议</span>
+            </label>
           </el-form-item>
         </el-form>
       </div>
-    </div>
-    <div class="login-footer"></div>
+    </main>
+
+    <footer class="login-footer"></footer>
   </div>
 </template>
 
 <script>
+import { GetLogo } from '@/api/app';
+import { setConfig } from '@/utils/auth';
+
 export default {
   name: 'Login',
   data() {
@@ -75,7 +83,7 @@ export default {
     };
 
     return {
-      isRemember: false,
+      isRemember: true,
       loading: false,
       isAgree: true,
       loginForm: {
@@ -88,6 +96,12 @@ export default {
       }
     };
   },
+  created() {
+    GetLogo().then(res => {
+      document.title = res.title;
+      setConfig(res);
+    });
+  },
   methods: {
     handleLogin() {
       this.$refs.loginForm.validate(valid => {
@@ -120,22 +134,23 @@ export default {
   width: 100%;
   min-width: 1000px;
   height: 100%;
+  padding-top: 55px;
   background: linear-gradient(rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0.45)),
     url('../../assets/login.png');
   background-size: cover;
-  padding-top: 55px;
 
   // 主容器
   &-container {
-    padding: 68px 8% 0;
     display: flex;
     justify-content: space-between;
+    padding: 68px 8% 0;
 
     &-logo {
       width: 136px;
       min-width: 136px;
       height: 136px;
       min-height: 136px;
+      overflow: hidden;
       background-color: #c4c4c4;
       border-radius: 25px;
     }
@@ -158,11 +173,11 @@ export default {
       border-radius: 8px;
 
       &-title {
-        color: #f90;
-        text-align: center;
+        margin-top: 48px;
         font-size: 20px;
         font-weight: 700;
-        margin-top: 48px;
+        color: $basic-color;
+        text-align: center;
       }
 
       &-form {
@@ -172,24 +187,28 @@ export default {
           padding-top: 20px;
 
           .forget-password {
+            color: $basic-color;
             text-align: right;
-            color: #f90;
           }
         }
 
         .login-button {
           width: 100%;
-          font-size: 18px;
           height: 48px;
+          font-size: 18px;
           font-weight: 700;
           color: #fff;
-          background-color: #f90;
+          background-color: $basic-color;
 
           &:hover {
             color: #efefef;
             background-color: #f19100;
           }
         }
+
+        .user-agreement {
+          color: $basic-color;
+        }
       }
     }
   }
@@ -197,9 +216,10 @@ export default {
   &-footer {
     position: fixed;
     bottom: 0;
-    background-color: #2c2c2c;
+    z-index: 1001;
     width: 100%;
     height: 154px;
+    background-color: #2c2c2c;
   }
 }
 </style>

+ 102 - 134
src/views/org_manager/AddOrg.vue

@@ -1,67 +1,58 @@
 <template>
   <div class="add-org">
-    <div class="add-org-container">
-      <el-form ref="form" :model="form" :rules="orgRules" label-position="left" label-width="120px">
-        <el-form-item prop="logo" label="LOGO">
-          <el-upload
-            action="no"
-            class="avatar-uploader"
-            :http-request="upload"
-            :before-upload="beforeUpload"
-            :show-file-list="false"
-            accept="image/*"
-          >
-            <img v-if="form.imageUrl" :src="form.imageUrl" class="avatar" />
-            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
-          </el-upload>
-        </el-form-item>
-
-        <el-form-item label="机构名称" prop="name">
-          <el-input ref="name" v-model="form.name" type="text" placeholder="请输入机构名称" />
-        </el-form-item>
-
-        <el-form-item label="机构介绍">
-          <el-input
-            v-model="form.intro"
-            type="textarea"
-            rows="5"
-            resize="none"
-            placeholder="请输入机构简介"
-          />
-        </el-form-item>
-
-        <el-form-item label="管理员用户名" prop="admin_user_name">
-          <el-input
-            ref="admin_user_name"
-            v-model="form.admin_user_name"
-            type="text"
-            placeholder="请输入管理员用户名"
-          />
-        </el-form-item>
-
-        <el-form-item label="管理员密码" prop="admin_user_password">
-          <el-input
-            ref="admin_user_password"
-            v-model="form.admin_user_password"
-            type="password"
-            placeholder="输入管理员密码"
-          />
-        </el-form-item>
-
-        <el-form-item label="确认密码" prop="confirm_password">
-          <el-input
-            ref="confirm_password"
-            v-model="form.confirm_password"
-            type="password"
-            placeholder="请确认密码"
-          />
-        </el-form-item>
-
-        <el-form-item>
-          <el-button class="add-button" @click="addOrg">创建</el-button>
-        </el-form-item>
-      </el-form>
-    </div>
+    <main class="add-org-container">
+      <div class="org-form">
+        <el-form ref="form" :model="form" :rules="orgRules" label-position="left" label-width="120px">
+          <el-form-item label="机构名称" prop="name">
+            <el-input ref="name" v-model="form.name" type="text" placeholder="请输入机构名称" />
+          </el-form-item>
+
+          <el-form-item label="机构介绍">
+            <el-input v-model="form.intro" type="textarea" rows="5" resize="none" placeholder="请输入机构简介" />
+          </el-form-item>
+
+          <el-form-item label="管理员用户名" prop="admin_user_name">
+            <el-input
+              ref="admin_user_name"
+              v-model="form.admin_user_name"
+              type="text"
+              placeholder="请输入管理员用户名"
+            />
+          </el-form-item>
+
+          <el-form-item label="管理员密码" prop="admin_user_password">
+            <el-input
+              ref="admin_user_password"
+              v-model="form.admin_user_password"
+              type="password"
+              placeholder="输入管理员密码"
+            />
+          </el-form-item>
+
+          <el-form-item label="确认密码" prop="confirm_password">
+            <el-input ref="confirm_password" v-model="form.confirm_password" type="password" placeholder="请确认密码" />
+          </el-form-item>
+
+          <el-form-item>
+            <el-button type="primary" class="add-button" @click="addOrg">创建</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <div class="org-image">
+        <el-upload
+          action="no"
+          class="avatar-uploader"
+          :http-request="upload"
+          :before-upload="beforeUpload"
+          :show-file-list="false"
+          accept="image/*"
+        >
+          <img v-if="form.imageUrl" :src="form.imageUrl" class="avatar" />
+          <i v-else class="el-icon-plus avatar-uploader-icon" />
+        </el-upload>
+      </div>
+    </main>
   </div>
 </template>
 
@@ -71,22 +62,6 @@ import { addOrg } from '@/api/org';
 
 export default {
   data() {
-    const validatorName = (rule, value, callback) => {
-      if (!value) {
-        callback(new Error('机构名称不能为空!'));
-      } else {
-        callback();
-      }
-    };
-
-    const validatorUserName = (rule, value, callback) => {
-      if (!value) {
-        callback(new Error('管理员用户名不能为空!'));
-      } else {
-        callback();
-      }
-    };
-
     const validateUserPassword = (rule, value, callback) => {
       if (value.length < 6) {
         callback(new Error('管理员密码必须大于六位!'));
@@ -96,9 +71,8 @@ export default {
     };
 
     const validateConfirmPassword = (rule, value, callback) => {
-      console.log(this.form.admin_user_password);
       if (this.form.admin_user_password !== value) {
-        callback(new Error('上下密码不一致!'));
+        callback(new Error('管理员密码与确认密码不一致!'));
       } else {
         callback();
       }
@@ -115,10 +89,10 @@ export default {
         confirm_password: ''
       },
       orgRules: {
-        name: [{ require: true, trigger: 'blur', validator: validatorName }],
-        admin_user_name: [{ require: true, trigger: 'blur', validator: validatorUserName }],
-        admin_user_password: [{ require: true, trigger: 'blur', validator: validateUserPassword }],
-        confirm_password: [{ require: true, trigger: 'blur', validator: validateConfirmPassword }]
+        name: [{ required: true, message: '机构名称不能为空' }],
+        admin_user_name: [{ required: true, message: '管理员用户名不能为空!' }],
+        admin_user_password: [{ required: true, validator: validateUserPassword }],
+        confirm_password: [{ required: true, validator: validateConfirmPassword }]
       }
     };
   },
@@ -131,8 +105,7 @@ export default {
       return isImage;
     },
     upload(file) {
-      fileUpload('Open', file).then(response => {
-        const { file_info_list } = response;
+      fileUpload('Open', file).then(({ file_info_list }) => {
         if (file_info_list.length > 0) {
           const { file_url, file_id } = file_info_list[0];
           this.form.imageUrl = file_url;
@@ -143,12 +116,9 @@ export default {
     addOrg() {
       this.$refs.form.validate(valid => {
         if (valid) {
-          addOrg(this.form).then(response => {
-            console.log(response);
-            if (response.status === 1) {
-              this.$message.success('创建课程成功!');
-              this.$router.push('/org_manager');
-            }
+          addOrg(this.form).then(() => {
+            this.$message.success('创建课程成功!');
+            this.$router.push('/org_manager');
           });
         } else {
           return false;
@@ -160,7 +130,8 @@ export default {
 </script>
 
 <style lang="scss">
-@import '~@/styles/mixin.scss';
+@import '~@/styles/mixin';
+$avatar-width: 310px;
 
 .add-org {
   @include container;
@@ -168,59 +139,56 @@ export default {
   padding: 44px 0 0;
 
   &-container {
+    display: flex;
     width: 100%;
-    height: 700px;
     padding: 48px 64px;
     background-color: #fff;
     border-radius: 8px;
 
-    .el-input,
-    .el-textarea {
-      width: 600px;
+    .org-form {
+      flex: 7;
+      margin-right: 12px;
+
+      .add-button {
+        width: 124px;
+        height: 40px;
+        font-size: 16px;
+        font-weight: 700;
+      }
     }
 
-    .avatar-uploader {
-      display: inline-block;
+    .org-image {
+      flex: 3;
 
-      & .el-upload {
-        border: 1px dashed #d9d9d9;
-        border-radius: 6px;
-        cursor: pointer;
-        position: relative;
-        overflow: hidden;
+      .avatar-uploader {
+        display: inline-block;
 
-        &:hover {
-          border-color: #409eff;
-        }
-      }
+        .el-upload {
+          position: relative;
+          overflow: hidden;
+          cursor: pointer;
+          border: 1px dashed #d9d9d9;
+          border-radius: 6px;
 
-      &-icon {
-        font-size: 28px;
-        color: #8c939d;
-        width: 90px;
-        height: 90px;
-        line-height: 90px;
-        text-align: center;
-      }
+          &:hover {
+            border-color: #409eff;
+          }
+        }
 
-      & .avatar {
-        width: 90px;
-        height: 90px;
-        display: block;
-      }
-    }
+        &-icon {
+          width: $avatar-width;
+          height: $avatar-width;
+          font-size: 28px;
+          line-height: $avatar-width;
+          color: #8c939d;
+          text-align: center;
+        }
 
-    .add-button {
-      width: 124px;
-      font-size: 16px;
-      height: 40px;
-      font-weight: 700;
-      color: #fff;
-      background-color: #f90;
-
-      &:hover {
-        color: #efefef;
-        background-color: #f19100;
+        .avatar {
+          display: block;
+          width: $avatar-width;
+          height: $avatar-width;
+        }
       }
     }
   }

+ 137 - 0
src/views/org_manager/ShowOrg.vue

@@ -0,0 +1,137 @@
+<template>
+  <el-dialog :visible="visible" title="查看机构信息" :before-close="close">
+    <main class="org">
+      <div class="org-info">
+        <el-descriptions :column="1" border :label-style="{ width: '150px', 'text-align': 'center' }">
+          <el-descriptions-item>
+            <template slot="label">
+              <span>名称</span>
+            </template>
+            <span>{{ orgInfo.name }}</span>
+          </el-descriptions-item>
+          <el-descriptions-item>
+            <template slot="label">
+              <span>注册教师人数</span>
+            </template>
+            <span>{{ orgInfo.teacher_count }}</span>
+          </el-descriptions-item>
+          <el-descriptions-item>
+            <template slot="label">
+              <span>审核通过的<br />注册教师人数</span>
+            </template>
+            <span>{{ orgInfo.teacher_count_audited }}</span>
+          </el-descriptions-item>
+          <el-descriptions-item>
+            <template slot="label">
+              <span>管理员用户名</span>
+            </template>
+            <span>{{ orgInfo.admin_user_name }}</span>
+          </el-descriptions-item>
+          <el-descriptions-item content-class-name="org-intro">
+            <template slot="label">
+              <span>介绍</span>
+            </template>
+            <span>{{ orgInfo.intro }}</span>
+          </el-descriptions-item>
+        </el-descriptions>
+      </div>
+
+      <div class="org-image">
+        <el-image :src="orgInfo.picture_url">
+          <div slot="error" class="image-slot">
+            <i class="el-icon-picture-outline" />
+          </div>
+        </el-image>
+      </div>
+    </main>
+
+    <footer slot="footer">
+      <el-button @click="close">关闭</el-button>
+    </footer>
+  </el-dialog>
+</template>
+
+<script>
+import { GetOrgInfo } from '@/api/org';
+
+export default {
+  props: {
+    orgId: {
+      default: '',
+      type: String
+    }
+  },
+  data() {
+    return {
+      visible: false,
+      orgInfo: {}
+    };
+  },
+  watch: {
+    visible(newValue) {
+      if (newValue) {
+        GetOrgInfo({ id: this.orgId }).then(res => {
+          this.orgInfo = res;
+        });
+      } else {
+        this.orgInfo = {};
+      }
+    }
+  },
+  methods: {
+    show() {
+      this.visible = true;
+    },
+    close() {
+      this.visible = false;
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.org {
+  display: flex;
+
+  &-info {
+    flex: 7;
+    margin-right: 12px;
+  }
+
+  &-image {
+    flex: 3;
+
+    .org-intro {
+      height: 80px;
+    }
+  }
+}
+</style>
+
+<style lang="scss">
+.org {
+  .el-image {
+    width: 100%;
+
+    .image-slot {
+      display: grid;
+      width: 100%;
+      margin-top: 120px;
+
+      .el-icon-picture-outline {
+        justify-self: center;
+        font-size: 60px;
+      }
+    }
+  }
+
+  &-info {
+    .org-intro > span {
+      display: inline-block;
+      height: 60px;
+      max-height: 60px;
+      overflow-y: auto;
+    }
+  }
+}
+</style>

+ 161 - 0
src/views/org_manager/UpdateOrg.vue

@@ -0,0 +1,161 @@
+<template>
+  <el-dialog :visible="visible" width="700px" title="修改机构" :before-close="close">
+    <main class="update-org">
+      <div class="update-org-info">
+        <el-form ref="form" :model="orgInfo" :rules="rules" :hide-required-asterisk="true" label-width="80px">
+          <el-form-item label="名称" prop="name">
+            <el-input v-model="orgInfo.name" autocomplete="off" />
+          </el-form-item>
+          <el-form-item label="介绍">
+            <el-input v-model="orgInfo.intro" type="textarea" :rows="6" resize="none" autocomplete="off" />
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <div class="update-org-image">
+        <el-upload
+          action="no"
+          class="avatar-uploader"
+          :http-request="upload"
+          :before-upload="beforeUpload"
+          :show-file-list="false"
+          accept="image/*"
+        >
+          <img v-if="orgInfo.picture_url" :src="orgInfo.picture_url" class="avatar" />
+          <i v-else class="el-icon-plus avatar-uploader-icon" />
+        </el-upload>
+      </div>
+    </main>
+
+    <footer slot="footer">
+      <el-button type="primary" @click="updateOrg">确定</el-button>
+      <el-button @click="close">关闭</el-button>
+    </footer>
+  </el-dialog>
+</template>
+
+<script>
+import { GetOrgInfo, UpdateOrg } from '@/api/org';
+import { fileUpload } from '@/api/app';
+
+export default {
+  props: {
+    orgId: {
+      default: '',
+      type: String
+    }
+  },
+  data() {
+    return {
+      visible: false,
+      orgInfo: {
+        name: '',
+        intro: '',
+        picture_url: '',
+        picture_id: ''
+      },
+      rules: {
+        name: [{ required: true, message: '名称不能为空' }]
+      }
+    };
+  },
+  watch: {
+    visible(newValue) {
+      if (newValue) {
+        GetOrgInfo({ id: this.orgId }).then(res => {
+          this.orgInfo = res;
+        });
+      } else {
+        this.orgInfo = {};
+      }
+    }
+  },
+  methods: {
+    updateOrg() {
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          const { name, intro, picture_id } = this.orgInfo;
+          UpdateOrg({ id: this.orgId, name, intro, picture_id }).then(() => {
+            this.$message.success('修改机构成功');
+            this.visible = false;
+          });
+        } else {
+          return false;
+        }
+      });
+    },
+
+    beforeUpload(file) {
+      let isImage = /^image/.test(file.type);
+      if (!isImage) {
+        this.$message.error('上传的文件不是图片,请重新上传!');
+      }
+      return isImage;
+    },
+    upload(file) {
+      fileUpload('Open', file).then(({ file_info_list }) => {
+        if (file_info_list.length > 0) {
+          const { file_url, file_id } = file_info_list[0];
+          this.orgInfo.picture_url = file_url;
+          this.orgInfo.picture_id = file_id;
+        }
+      });
+    },
+
+    show() {
+      this.visible = true;
+    },
+    close() {
+      this.visible = false;
+    }
+  }
+};
+</script>
+
+<style lang="scss">
+$avatar-w: 198px;
+
+.update-org {
+  display: flex;
+
+  &-info {
+    flex: 7;
+    margin-right: 12px;
+  }
+
+  &-image {
+    flex: 3;
+
+    .avatar-uploader {
+      display: inline-block;
+
+      .el-upload {
+        position: relative;
+        overflow: hidden;
+        cursor: pointer;
+        border: 1px dashed #d9d9d9;
+        border-radius: 6px;
+
+        &:hover {
+          border-color: #409eff;
+        }
+      }
+
+      &-icon {
+        width: $avatar-w;
+        height: $avatar-w;
+        font-size: 28px;
+        line-height: $avatar-w;
+        color: #8c939d;
+        text-align: center;
+      }
+
+      .avatar {
+        display: block;
+        width: $avatar-w;
+        height: $avatar-w;
+      }
+    }
+  }
+}
+</style>

+ 49 - 28
src/views/org_manager/index.vue

@@ -1,11 +1,6 @@
 <template>
   <div class="org-manager">
-    <el-input
-      v-model="search"
-      type="text"
-      prefix-icon="el-icon-search"
-      @keyup.enter.native="queryOrgList"
-    >
+    <el-input v-model="search" type="text" prefix-icon="el-icon-search" @keyup.enter.native="queryOrgList">
       <el-button slot="append" icon="el-icon-search" @click="queryOrgList"></el-button>
     </el-input>
     <div class="org-manager-list">
@@ -20,20 +15,22 @@
         <el-table-column prop="teacher_count" label="注册教师人数" width="110" />
         <el-table-column prop="teacher_count_audited" label="审核通过的注册教师人数" width="180" />
         <el-table-column prop="admin_user_name" label="机构管理员" />
-        <el-table-column fixed="right" width="180">
-          <template slot-scope="scope">
-            <el-row type="flex" justify="space-between">
-              <el-col>
-                <el-link :underline="false" @click="handleShow(scope.$index, scope.row)">
-                  查看
-                </el-link>
-              </el-col>
-              <el-col>
-                <el-link :underline="false" @click="handleShow(scope.$index, scope.row)">
-                  管理
-                </el-link>
-              </el-col>
-            </el-row>
+        <el-table-column fixed="right" width="70">
+          <template slot-scope="{ row }">
+            <a @click="showOrg(row.id)">查看</a>
+          </template>
+        </el-table-column>
+        <el-table-column fixed="right" width="120">
+          <template slot-scope="{ row }">
+            <el-dropdown placement="top">
+              <a class="el-dropdown-link">管理</a>
+              <el-dropdown-menu slot="dropdown">
+                <el-dropdown-item @click.native="updateOrg(row.id)">修改</el-dropdown-item>
+                <el-dropdown-item @click.native="resetOrgAdminPassword(row.admin_user_id)">
+                  重置机构管理员密码
+                </el-dropdown-item>
+              </el-dropdown-menu>
+            </el-dropdown>
           </template>
         </el-table-column>
       </el-table>
@@ -50,21 +47,35 @@
       @current-change="changePage"
       @size-change="changePageSize"
     />
+
+    <reset-password ref="reset" :user-id="curUserId" />
+    <show-org ref="showOrg" :org-id="curOrgId" />
+    <update-org ref="updateOrg" :org-id="curOrgId" />
   </div>
 </template>
 
 <script>
+import ResetPassword from '@/components/ResetPassword';
+import ShowOrg from './ShowOrg';
+import UpdateOrg from './UpdateOrg';
 import { pageQueryOrgList } from '@/api/list';
 
 export default {
   name: 'OrgManager',
+  components: {
+    ResetPassword,
+    ShowOrg,
+    UpdateOrg
+  },
   data() {
     return {
       search: '',
       page_capacity: 10,
       cur_page: 1,
       org_list: [],
-      total_count: 0
+      total_count: 0,
+      curUserId: '',
+      curOrgId: ''
     };
   },
   created() {
@@ -80,27 +91,37 @@ export default {
       this.queryOrgList();
     },
     queryOrgList() {
-      let data = {
+      pageQueryOrgList({
         name: this.search,
         page_capacity: this.page_capacity,
         cur_page: this.cur_page
-      };
-      pageQueryOrgList(data).then(response => {
-        let { cur_page, org_list, total_count } = response;
+      }).then(({ cur_page, org_list, total_count }) => {
         this.cur_page = cur_page;
         this.org_list = org_list;
         this.total_count = total_count;
       });
     },
-    handleShow(i, row) {
-      console.log(i, row);
+
+    showOrg(id) {
+      this.curOrgId = id;
+      this.$refs.showOrg.show();
+    },
+
+    updateOrg(id) {
+      this.curOrgId = id;
+      this.$refs.updateOrg.show();
+    },
+
+    resetOrgAdminPassword(id) {
+      this.curUserId = id;
+      this.$refs.reset.show();
     }
   }
 };
 </script>
 
 <style lang="scss" scope>
-@import '~@/styles/mixin.scss';
+@import '~@/styles/mixin';
 
 .org-manager {
   @include container;

+ 8 - 20
src/views/teacher_manager/index.vue

@@ -20,11 +20,7 @@
           />
         </el-col>
         <el-col :span="2">
-          <el-button
-            class="search-button"
-            icon="el-icon-search"
-            @click="queryOrgTeacherUserList"
-          ></el-button>
+          <el-button class="search-button" icon="el-icon-search" @click="queryOrgTeacherUserList"></el-button>
         </el-col>
       </el-row>
     </div>
@@ -40,8 +36,8 @@
         <el-table-column prop="user_phone" label="手机号" width="120" />
         <el-table-column prop="user_email" label="邮箱" width="180" />
         <el-table-column prop="is_audited" label="已审核">
-          <template slot-scope="scope">
-            <span>{{ scope.row.is_audited === 'true' ? '√' : '' }}</span>
+          <template slot-scope="{ row }">
+            <div :style="{ 'text-align': 'center', width: '40px' }">{{ row.is_audited === 'true' ? '√' : '' }}</div>
           </template>
         </el-table-column>
         <el-table-column fixed="right" width="180">
@@ -62,11 +58,7 @@
                     <span class="popedom-manager">权限管理</span>
                     <div v-for="item in popedom_list" :key="item.popedom_code" class="popedom-list">
                       <span>{{ item.popedom_name }}</span>
-                      <el-switch
-                        v-model="item.is_selected"
-                        active-color="#34CC83"
-                        inactive-color="#C4C4C4"
-                      />
+                      <el-switch v-model="item.is_selected" active-color="#34CC83" inactive-color="#C4C4C4" />
                     </div>
                     <el-button type="primary" @click="setPopedom(scope.row.id)">保存</el-button>
                   </div>
@@ -95,11 +87,7 @@
 
 <script>
 import { pageQueryOrgTeacherUserList } from '@/api/list';
-import {
-  auditOrgTeacherUser,
-  getPopedomList_OrgTeacherUse,
-  setPopedom_OrgTeacherUser
-} from '@/api/teacher';
+import { auditOrgTeacherUser, getPopedomList_OrgTeacherUse, setPopedom_OrgTeacherUser } from '@/api/teacher';
 
 export default {
   name: 'TeacherManager',
@@ -210,7 +198,7 @@ export default {
 </script>
 
 <style lang="scss">
-@import '~@/styles/mixin.scss';
+@import '~@/styles/mixin';
 
 .teacher-manager {
   @include container;
@@ -247,16 +235,16 @@ export default {
 .popedom {
   &-manager {
     display: flex;
-    font-weight: 700;
     justify-content: space-between;
     padding-bottom: 8px;
+    font-weight: 700;
     border-bottom: 1px solid #d9d9d9;
   }
 
   &-list {
-    padding-top: 10px;
     display: flex;
     justify-content: space-between;
+    padding-top: 10px;
   }
 
   .el-button {

+ 18 - 12
stylelint.config.js

@@ -1,16 +1,17 @@
 module.exports = {
   defaultSeverity: 'warning',
-  extends: 'stylelint-config-standard',
-  plugins: ['stylelint-declaration-block-no-ignored-properties', 'stylelint-order'],
+  extends: [
+    'stylelint-config-standard',
+    'stylelint-scss',
+    'stylelint-config-sass-guidelines',
+    'stylelint-config-recess-order'
+  ],
+  plugins: ['stylelint-declaration-block-no-ignored-properties'],
   rules: {
     'plugin/declaration-block-no-ignored-properties': true,
-    // 各分类属性顺序
-    'order/order': ['at-rules', 'custom-properties', 'dollar-variables', 'declarations', 'rules'],
+    'order/properties-alphabetical-order': null,
     // 指定2个空格
     indentation: 2,
-    // 多个选择器样式之间允许有空行
-    // 'rule-empty-line-before': null,
-    'declaration-colon-newline-after': null,
     // 样式块中不允许重复的属性
     'declaration-block-no-duplicate-properties': true,
     // 指定颜色函数使用传统符号隔开
@@ -19,16 +20,16 @@ module.exports = {
     'function-url-no-scheme-relative': true,
     // 可组合成一个属性的写法,不允许拆开书写
     'declaration-block-no-redundant-longhand-properties': true,
-    // 选择器最大深度为4
-    'selector-max-compound-selectors': 6,
-    // 限制 id 选择器的数目在一个选择器中
+    // 选择器最大深度
+    'selector-max-compound-selectors': 8,
+    // 限制 id选择器的数目在一个选择器中
     'selector-max-id': 1,
     // 最多2个类型选择器
     'selector-max-type': 2,
     // 不允许未知的动画
     'no-unknown-animations': true,
     // 在字体名称必须使用引号的地方使用引号,其他地方不能使用
-    'font-family-name-quotes': 'always-where-required',
+    'font-family-name-quotes': 'always-unless-keyword',
     // url 函数内部必须有引号
     'function-url-quotes': 'always',
     // 指定字符串引号为单引号
@@ -39,6 +40,11 @@ module.exports = {
     'no-empty-first-line': true,
     // 不允许使用 unicode 作为顺序标记
     'unicode-bom': 'never',
-    'at-rule-no-unknown': null
+    'at-rule-no-unknown': [true, { ignoreAtRules: ['import', 'include', 'mixin', 'include', 'extend'] }],
+    'max-nesting-depth': 8,
+    'selector-no-qualifying-type': [true, { ignore: ['attribute', 'class', 'id'] }],
+    // 为类选择器指定一个模式
+    'selector-class-pattern': null,
+    'declaration-colon-newline-after': null
   }
 };

Vissa filer visades inte eftersom för många filer har ändrats