Browse Source

项目更新

guhongwei 3 years ago
parent
commit
0c448fc1bd

+ 11 - 0
src/assets/css/color-dark.css

@@ -38,7 +38,18 @@
 }
 .el-menu-item {
   color: #ffffff;
+  background-color: #242f42 !important;
 }
 .el-menu-item.is-active {
   background-color: #142832 !important;
 }
+.el-submenu__title *{
+  color: #ffffff;
+}
+.el-submenu__title:hover {
+  background-color: #142832 !important;
+}
+
+.el-submenu__title{
+  background-color: #242f42 !important;
+}

+ 14 - 3
src/assets/css/theme-ele/color-ele.css

@@ -41,11 +41,22 @@
 }
 .el-menu-item.is-active {
   color: #ffffff;
-  background-color: #403AFF !important;
+  background-color: #403aff !important;
 }
-.el-menu-item:hover{
-   background-color: #403AFF !important;
+.el-menu-item:hover {
+  background-color: #403aff !important;
 }
 .sidebar-el-menu:not(.el-menu--collapse) {
   background-color: #409eff !important;
 }
+.el-submenu__title:hover {
+  background-color: #403aff !important;
+}
+.el-submenu__title {
+  background-color: #409eff !important;
+}
+
+.el-menu-item {
+  background-color: #409eff !important;
+  color: #ffffff;
+}

+ 14 - 3
src/assets/css/theme-green/color-green.css

@@ -40,12 +40,23 @@
   background-color: #00d1b2 !important;
 }
 .el-menu-item.is-active {
-  color: #ffffff;
+  color: #000000;
   background-color: #00a78e !important;
 }
-.el-menu-item:hover{
-   background-color: #00a78e !important;
+.el-menu-item:hover {
+  background-color: #00a78e !important;
 }
 .sidebar-el-menu:not(.el-menu--collapse) {
   background-color: #00d1b2 !important;
 }
+.el-submenu__title:hover {
+  background-color: #00a78e !important;
+}
+.el-submenu__title {
+  background-color: #07c4a8 !important;
+}
+
+.el-menu-item {
+  background-color: #07c4a8 !important;
+  color: #ffffff;
+}

+ 12 - 0
src/assets/css/theme-pink/color-pink.css

@@ -49,3 +49,15 @@
 .sidebar-el-menu:not(.el-menu--collapse) {
   background-color: #D23CE6 !important;
 }
+
+.el-submenu__title:hover {
+  background-color: #D23CE6 !important;
+}
+.el-submenu__title {
+  background-color: #D23CE6 !important;
+}
+
+.el-menu-item {
+  background-color: #D23CE6 !important;
+  color: #ffffff;
+}

+ 11 - 0
src/assets/css/theme-red/color-red.css

@@ -49,3 +49,14 @@
 .sidebar-el-menu:not(.el-menu--collapse) {
   background-color: #e31d33 !important;
 }
+.el-submenu__title {
+  background-color: #e31d33 !important;
+}
+.el-submenu__title:hover {
+  background-color: #640F33 !important;
+}
+
+.el-menu-item {
+  background-color: #e31d33 !important;
+  color: #ffffff;
+}

+ 2 - 3
src/components/admin-frame/Header.vue

@@ -12,8 +12,7 @@
           </el-col>
           <el-col :span="12" class="right">
             <i class="el-icon-user-solid"></i>
-            <!-- <span>{{ user.name || '游客' }}</span> -->
-            <span>游客</span>
+            <span>{{ user ? user.name : '游客' }}</span>
             <el-button type="danger" size="mini" @click="logout">退出登录</el-button>
           </el-col>
         </el-col>
@@ -42,7 +41,7 @@ export default {
     },
     // 退出登录
     logout() {
-      localStorage.removeItem('token');
+      sessionStorage.removeItem('token');
       this.$router.push('/login');
     },
   },

+ 27 - 5
src/components/admin-frame/Sidebar.vue

@@ -14,6 +14,7 @@
             router
           >
             <template v-for="item in items">
+              <!-- 二级菜单 -->
               <template v-if="item.subs">
                 <el-submenu :index="item.index" :key="item.index">
                   <template slot="title">
@@ -21,14 +22,29 @@
                     <span slot="title">{{ item.title }}</span>
                   </template>
                   <template v-for="subItem in item.subs">
+                    <!-- 三级菜单 -->
                     <el-submenu v-if="subItem.subs" :index="subItem.index" :key="subItem.index">
-                      <template slot="title">{{ subItem.title }}</template>
-                      <el-menu-item v-for="(threeItem, i) in subItem.subs" :key="i" :index="threeItem.index">{{ threeItem.title }}</el-menu-item>
+                      <template slot="title">
+                        <i :class="['iconfont', subItem.icon]"></i>
+                        <span slot="title">{{ subItem.title }}</span>
+                      </template>
+                      <el-menu-item v-for="(threeItem, i) in subItem.subs" :key="i" :index="threeItem.index">
+                        <template slot="title">
+                          <i :class="['iconfont', threeItem.icon]"></i>
+                          <span slot="title">{{ threeItem.title }}</span>
+                        </template>
+                      </el-menu-item>
                     </el-submenu>
-                    <el-menu-item v-else :index="subItem.index" :key="subItem.index">{{ subItem.title }}</el-menu-item>
+                    <el-menu-item v-else :index="subItem.index" :key="subItem.index">
+                      <template slot="title">
+                        <i :class="['iconfont', subItem.icon]"></i>
+                        <span slot="title">{{ subItem.title }}</span>
+                      </template>
+                    </el-menu-item>
                   </template>
                 </el-submenu>
               </template>
+              <!-- 一级菜单 -->
               <template v-else>
                 <el-menu-item class="first" :index="item.index" :key="item.index">
                   <i :class="['iconfont', item.icon]"></i>
@@ -44,7 +60,7 @@
 </template>
 
 <script>
-const { system, userMenu } = require('../../layout/deploy/menu');
+const { system, uMenu, aMenu, eMenu } = require('../../layout/deploy/menu');
 const { menuInfo } = require('../../layout/deploy/site');
 import { mapState, createNamespacedHelpers } from 'vuex';
 import _ from 'lodash';
@@ -68,8 +84,14 @@ export default {
   },
   methods: {
     getMenu() {
+      let type = sessionStorage.getItem('type');
+      if (!_.get(this.user, 'id')) return;
       let list = _.cloneDeep(this.items);
-      list.push(...userMenu);
+      let sMenu = [];
+      if (type == '1') sMenu = uMenu;
+      else if (type == '2') sMenu = aMenu;
+      else if (type == '3') sMenu = eMenu;
+      list.push(...sMenu);
       this.$set(this, `items`, _.uniqBy(list, 'index'));
     },
   },

+ 49 - 0
src/components/frame/e-dialog.vue

@@ -0,0 +1,49 @@
+<template>
+  <div id="e-dialog">
+    <el-dialog :title="dialog.title" :visible.sync="dialog.show" width="40%" :before-close="toClose" :close-on-click-modal="false">
+      <slot name="info"></slot>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'e-dialog',
+  props: {
+    dialog: { type: Object, default: () => {} },
+  },
+  components: {},
+  data: function() {
+    return {};
+  },
+  created() {},
+  methods: {
+    toClose() {
+      this.$emit('toClose');
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+/deep/.el-dialog__body {
+  padding: 10px;
+  min-height: 30px;
+  max-height: 400px;
+  overflow-y: auto;
+}
+</style>

+ 10 - 7
src/components/frame/filter-page-table.vue

@@ -1,8 +1,8 @@
 <template>
   <div id="data-table">
-    <el-form :model="searchInfo" :inline="true" style="padding:0.9rem·1.875rem" size="mini" v-if="useFilter">
-      <el-row type="flex">
-        <el-col :span="22">
+    <el-form :model="searchInfo" :inline="true" style="padding:8px 0" size="mini">
+      <el-row type="flex" justify="end">
+        <el-col :span="22" v-if="useFilter">
           <el-form-item v-for="(item, index) in filterList" :key="index">
             <template v-if="item.filter === 'select'">
               <el-select
@@ -76,7 +76,7 @@
               :label="item.label"
               :prop="item.prop"
               :formatter="toFormatter"
-              sortable
+              :sortable="sortable"
               v-bind="item.options"
               :show-overflow-tooltip="item.showTip || true"
             >
@@ -109,7 +109,7 @@
                   size="mini"
                   style="padding-right:10px"
                   :underline="false"
-                  @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index)"
+                  @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index, item.confirmWord)"
                 >
                   {{ item.label }}
                 </el-link>
@@ -158,6 +158,7 @@ export default {
     sumres: { type: String, default: 'total' },
     filter: { type: Array, default: () => [] },
     operaWidth: { type: Number, default: 200 },
+    sortable: { type: Boolean, default: true },
     limit: { type: Number, default: _.get(this, `$limit`, undefined) !== undefined ? this.$limit : process.env.VUE_APP_LIMIT * 1 || 10 },
   },
   components: {},
@@ -190,7 +191,7 @@ export default {
         } else return cellValue;
       }
     },
-    handleOpera(data, method, confirm = false, methodZh, label, index) {
+    handleOpera(data, method, confirm = false, methodZh, label, index, confirmWord) {
       let self = true;
       if (_.isFunction(methodZh)) {
         methodZh = methodZh(data);
@@ -199,7 +200,9 @@ export default {
         self = false;
       }
       if (confirm) {
-        this.$confirm(self ? methodZh : `您确认${methodZh}该数据?`, '提示', {
+        let word = self ? methodZh : `您确认${methodZh}该数据?`;
+        if (confirmWord) word = confirmWord;
+        this.$confirm(word, '提示', {
           confirmButtonText: '确定',
           cancelButtonText: '取消',
           type: 'warning',

+ 130 - 0
src/components/frame/s-upload.vue

@@ -0,0 +1,130 @@
+<template>
+  <div id="upload">
+    <el-upload
+      v-if="url"
+      ref="upload"
+      :action="url"
+      :list-type="listType"
+      :file-list="fileList"
+      :limit="limit"
+      :on-exceed="outLimit"
+      :on-preview="handlePictureCardPreview"
+      :before-remove="handleRemove"
+      :on-success="onSuccess"
+      :before-upload="beforeUpload"
+      :show-file-list="showList"
+      :accept="accept"
+    >
+      <el-button size="small" type="primary" v-if="isBtn">点击上传</el-button>
+      <template v-else-if="uploadBtn">
+        <el-button type="danger">选择文件</el-button>
+      </template>
+      <template v-else>
+        <el-button type="primary" size="mini">选择文件</el-button>
+      </template>
+      <template #tip v-if="tip">
+        {{ tip }}
+      </template>
+    </el-upload>
+    <el-dialog :visible.sync="dialogVisible" append-to-body>
+      <img width="100%" :src="dialogImageUrl" alt="" />
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import _ from 'lodash';
+export default {
+  name: 'upload',
+  props: {
+    url: { type: null },
+    limit: { type: Number },
+    data: { type: null },
+    type: { type: String },
+    isBtn: { type: Boolean, default: false },
+    uploadBtn: { type: Boolean, default: false },
+    showList: { type: Boolean, default: true },
+    accept: { type: String, default: '' },
+    tip: { type: String, default: undefined },
+    listType: { type: String, default: 'picture-card' },
+    file_type: { type: String, default: 'jpeg' },
+  },
+  components: {},
+  data: () => ({
+    dialogVisible: false,
+    dialogImageUrl: '',
+    fileList: [],
+  }),
+  created() {
+    if (this.data) {
+      this.defalutProcess(this.data);
+    }
+  },
+  watch: {
+    data: {
+      handler(val) {
+        this.defalutProcess(val);
+      },
+    },
+  },
+  computed: {},
+  methods: {
+    handlePictureCardPreview(file) {
+      this.dialogImageUrl = file.url;
+      this.dialogVisible = true;
+    },
+    handleRemove(file, fileList) {
+      this.$set(this, `fileList`, []);
+      // let index = fileList.findIndex(f => _.isEqual(f, file));
+      this.$emit('delete', { file, type: this.type });
+      return false;
+    },
+    outLimit() {
+      this.$message.error(`只允许上传${this.limit}个文件`);
+    },
+    onSuccess(response, file, fileList) {
+      //将文件整理好传回父组件
+      this.$emit('upload', { type: this.type, data: { ...response, name: file.name } });
+    },
+    beforeUpload(file) {
+      let setting_type = this.file_type.split('|');
+      let file_type = file.type.split('/')[1];
+      let isType = false;
+      for (const val of setting_type) {
+        if (val == file_type) isType = true;
+      }
+      // 文件大小改为10Mb
+      const isLt20M = file.size / 1024 / 1024 < 10;
+      if (!isType) {
+        this.$message.error('图片格式不正确');
+      }
+      if (!isLt20M) {
+        this.$message.error('文件超出10M');
+      }
+      return isType && isLt20M;
+    },
+    defalutProcess(val) {
+      if (_.isArray(val)) {
+        let newArr = val.map(item => {
+          let object = {};
+          object.name = item.name;
+          object.url = item.url;
+          return object;
+        });
+        this.$set(this, `fileList`, newArr);
+      } else if (_.isObject(val)) {
+        let object = {};
+        if (_.get(val, `url`)) {
+          object.name = val.name;
+          object.url = val.url;
+          this.$set(this, `fileList`, [object]);
+        }
+      } else if (typeof val === 'string') {
+        this.$set(this, `fileList`, [{ name: '附件', url: val }]);
+      }
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 45 - 2
src/layout/deploy/menu.js

@@ -1,8 +1,51 @@
-export const system = [{ icon: 'icon-shouye', index: '/adminCenter/homeIndex', title: '系统首页' }];
-export const userMenu = [
+export const system = [
+  {
+    icon: 'icon-shouye',
+    index: '/adminCenter/homeIndex',
+    title: '系统首页',
+  },
+  {
+    icon: 'icon-shouye',
+    index: '2',
+    title: '系统设置',
+    subs: [
+      {
+        icon: 'icon-shouye',
+        index: '/system/basic',
+        title: '基本信息',
+      },
+      {
+        icon: 'icon-shouye',
+        index: '/system/updatepd',
+        title: '修改密码',
+      },
+    ],
+  },
+];
+export const uMenu = [
   // {
   //   icon: 'icon-ceshi',
   //   index: '/adminCenter/test/index',
   //   title: '测试页面',
   // },
 ];
+export const aMenu = [
+  {
+    icon: 'icon-shouye',
+    index: '3',
+    title: '用户管理',
+    subs: [
+      {
+        icon: 'icon-shouye',
+        index: '/admin/personal/user',
+        title: '个人用户',
+      },
+      {
+        icon: 'icon-shouye',
+        index: '/admin/personal/expert',
+        title: '专家用户',
+      },
+    ],
+  },
+];
+export const eMenu = [];

+ 59 - 0
src/store/admin.js

@@ -0,0 +1,59 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+const jwt = require('jsonwebtoken');
+Vue.use(Vuex);
+const api = {
+  test: `/achieveAdmin/api/admin`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.test}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.test}/${payload}`);
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.test}`, payload);
+    return res;
+  },
+  async update({ commit }, { _id, ...info } = {}) {
+    const res = await this.$axios.$post(`${api.test}/${_id}`, { ...info });
+    return res;
+  },
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.test}/${payload}`);
+    return res;
+  },
+  async login({ commit }, user) {
+    const res = await this.$axios.$post(`${api.test}/login`, user);
+    if (res.errcode === 0) {
+      sessionStorage.setItem('token', res.data);
+      sessionStorage.setItem('type', user.type);
+      user = jwt.decode(res.data);
+      commit('setUser', user, { root: true });
+    }
+    return res;
+  },
+  async updatepd({ commit }, { _id, ...info } = {}) {
+    const res = await this.$axios.$post(`${api.test}/updatePwd/${_id}`, {
+      ...info,
+    });
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 53 - 0
src/store/expert.js

@@ -0,0 +1,53 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import _ from 'lodash';
+const jwt = require('jsonwebtoken');
+Vue.use(Vuex);
+const api = {
+  test: `/achieveAdmin/api/expert`,
+};
+const state = () => ({});
+const mutations = {};
+
+const actions = {
+  async query({ commit }, { skip = 0, limit, ...info } = {}) {
+    const res = await this.$axios.$get(`${api.test}`, {
+      skip,
+      limit,
+      ...info,
+    });
+    return res;
+  },
+  async fetch({ commit }, payload) {
+    const res = await this.$axios.$get(`${api.test}/${payload}`);
+    return res;
+  },
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.test}`, payload);
+    return res;
+  },
+  async update({ commit }, { _id, ...info } = {}) {
+    const res = await this.$axios.$post(`${api.test}/${_id}`, { ...info });
+    return res;
+  },
+  async delete({ commit }, payload) {
+    const res = await this.$axios.$delete(`${api.test}/${payload}`);
+    return res;
+  },
+  async login({ commit }, user) {
+    const res = await this.$axios.$post(`${api.test}/login`, user);
+    if (res.errcode === 0) {
+      sessionStorage.setItem('token', res.data);
+      sessionStorage.setItem('type', user.type);
+      user = jwt.decode(res.data);
+      commit('setUser', user, { root: true });
+    }
+    return res;
+  },
+};
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+};

+ 18 - 8
src/store/test.js

@@ -1,9 +1,10 @@
 import Vue from 'vue';
 import Vuex from 'vuex';
 import _ from 'lodash';
+const jwt = require('jsonwebtoken');
 Vue.use(Vuex);
 const api = {
-  test: `/api/serviceStudy/test`,
+  test: `/achieveAdmin/api/user`,
 };
 const state = () => ({});
 const mutations = {};
@@ -17,23 +18,32 @@ const actions = {
     });
     return res;
   },
-  async create({ commit }, payload) {
-    const res = await this.$axios.$post(`${api.test}`, payload);
-    return res;
-  },
   async fetch({ commit }, payload) {
     const res = await this.$axios.$get(`${api.test}/${payload}`);
     return res;
   },
-  async update({ commit }, { id, ...data }) {
-    const res = await this.$axios.$post(`${api.test}/update/${id}`, data);
+  async create({ commit }, payload) {
+    const res = await this.$axios.$post(`${api.test}`, payload);
+    return res;
+  },
+  async update({ commit }, { _id, ...info } = {}) {
+    const res = await this.$axios.$post(`${api.test}/${_id}`, { ...info });
     return res;
   },
-
   async delete({ commit }, payload) {
     const res = await this.$axios.$delete(`${api.test}/${payload}`);
     return res;
   },
+  async login({ commit }, user) {
+    const res = await this.$axios.$post(`${api.test}/login`, user);
+    if (res.errcode === 0) {
+      sessionStorage.setItem('token', res.data);
+      sessionStorage.setItem('type', user.type);
+      user = jwt.decode(res.data);
+      commit('setUser', user, { root: true });
+    }
+    return res;
+  },
 };
 export default {
   namespaced: true,

+ 2 - 27
src/store/user/mutations.js

@@ -1,34 +1,9 @@
 export const setUser = (state, payload) => {
   state.user = payload;
-  // let res = true;
-  // //登陆时
-  // if (payload) {
-  //   state.token = payload;
-  // } else {
-  //   //已经登陆,切换路由时取出客户信息放在总store中
-  //   let token = localStorage.getItem('token');
-  //   if (token && token !== 'guest') {
-  //     state.user = jwt.decode(token);
-  //   } else if (token && token == 'guest') {
-  //     let user = localStorage.getItem('user');
-  //     state.user = JSON.parse(user);
-  //   } else {
-  //     let timestamp = new Date().getTime();
-  //     let user = {
-  //       // id: `guest${timestamp}`,
-  //       name: `游客${timestamp}`,
-  //     };
-  //     state.user = user;
-  //     localStorage.setItem('token', 'guest');
-  //     localStorage.setItem('user', JSON.stringify(user));
-  //     console.warn('游客身份');
-  //   }
-  // }
-  // return res;
 };
 
 export const deleteUser = (state, payload) => {
   state.user = {};
-  localStorage.removeItem('token');
-  localStorage.removeItem('type');
+  sessionStorage.removeItem('token');
+  sessionStorage.removeItem('type');
 };