guhongwei 5 vuotta sitten
vanhempi
commit
95a5f35edc

+ 2 - 1
.env

@@ -1,2 +1,3 @@
 VUE_APP_AXIOS_BASE_URL = ''
-VUE_APP_ROUTER="/www"
+VUE_APP_ROUTER="/platadmin"
+VUE_APP_LIMIT = 10

+ 25 - 2
src/App.vue

@@ -1,7 +1,30 @@
 <template>
   <div id="app">
-    <router-view />
+    <main-layout></main-layout>
   </div>
 </template>
+<script>
+import mainLayout from '@/layout/main-layout.vue';
+export default {
+  name: 'app',
+  components: {
+    mainLayout,
+  },
+};
+</script>
 
-<style lang="less"></style>
+<style lang="less">
+html {
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+body {
+  margin: 0;
+  overflow-x: hidden;
+}
+.textOver {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+</style>

BIN
src/assets/logo.png


+ 166 - 0
src/layout/layout-part/heads.vue

@@ -0,0 +1,166 @@
+<template>
+  <div id="heads">
+    <el-row>
+      <div class="headTop">
+        <a href="" class="headImg">
+          <img src="../../assets/logo.png" width="50" height="50" />
+        </a>
+        <h3 class="headCompany">吉林省计算中心科技服务平台管理后台</h3>
+      </div>
+      <div class="headBtn">
+        <span class="mr14">|</span>
+        <span class="mr14">
+          <span class="el-icon-s-custom info_icon"></span>
+          &nbsp;{{ user.name || '请登录' }}
+        </span>
+        <span class="mr14">|</span>
+        <span style="color: #333;" @click="toLogout"
+          ><span class="el-icon-switch-button info_icon"></span>
+          &nbsp;退出
+        </span>
+      </div>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { mapActions, mapState, mapMutations, createNamespacedHelpers } from 'vuex';
+const { mapActions: login } = createNamespacedHelpers('login');
+export default {
+  name: 'heads',
+  props: {},
+  components: {},
+  data: () => ({}),
+  created() {},
+  watch: {},
+  computed: {
+    ...mapState(['user']),
+  },
+  methods: {
+    ...login(['logout']),
+    toLogout() {
+      localStorage.removeItem('token');
+      //TODO 跳转到登陆
+      window.location.href = 'http://free.liaoningdoupo.com/platlogin';
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+img {
+  max-height: 100%;
+  max-width: 100%;
+}
+a {
+  text-decoration: none;
+}
+.headTop {
+  float: left;
+  width: 50%;
+  padding: 0 0 0 50px;
+}
+.headImg {
+  float: left;
+  width: 60px;
+  height: 60px;
+  margin: 4px 0 0 0;
+  text-align: center;
+}
+.headXinyong {
+  float: left;
+  width: 70px;
+  height: 40px;
+  margin: 13px 0 0 10px;
+}
+.headCompany {
+  float: left;
+  font-size: 21px;
+  width: 500px;
+  padding: 18px 10px;
+  margin: 0;
+  color: #333;
+  font-family: 'inherit';
+  font-weight: 500;
+}
+.headBtn {
+  float: right;
+  width: 40%;
+  text-align: right;
+  padding: 0 60px 0 0;
+  margin-top: 20px;
+  font-size: 14px;
+  color: #333;
+}
+.headBtn .mr14 {
+  margin-right: 14px;
+  color: #333;
+}
+.headBtn .el-button {
+  border-radius: 0px;
+  border: none;
+  width: 0;
+  height: 0px;
+}
+.headBtn .el-button:hover {
+  background: none;
+}
+.popover-content {
+  margin: 0;
+  padding: 0;
+  .el-col {
+    border-bottom: 1px dashed #cccccc;
+    font-size: 0.8rem;
+    height: 1.25rem;
+  }
+}
+/deep/.el-popper {
+  border: 1px solid #ccc;
+  border-radius: 0px;
+  height: 100px;
+  padding: 0;
+}
+/deep/.popoverCon {
+  width: 400px;
+  height: 70px;
+  text-align: center;
+  padding: 0;
+  margin: 0;
+}
+/deep/.popoverCon li {
+  list-style: none;
+}
+/deep/.popoverBtn {
+  position: absolute;
+  bottom: 0;
+  left: 0px;
+  width: 424px;
+  height: 30px;
+  line-height: 30px;
+  text-align: right;
+  color: #333;
+  border-radius: 0 0 4px 4px;
+  background: #f6f6f6;
+  margin: 0;
+  padding: 0;
+}
+/deep/.popoverBtn:hover {
+  text-decoration: underline;
+  color: #409eff;
+}
+/deep/.el-form-item__label {
+  padding: 0px 0px 0 0;
+}
+/deep/.el-dialog__header {
+  background-color: #40a44c;
+}
+/deep/.el-icon-close:before {
+  color: #000;
+}
+/deep/.el-dialog__footer {
+  padding: 0px 20px 10px;
+}
+/deep/.el-dialog__body {
+  padding: 15px 20px;
+}
+</style>

+ 116 - 0
src/layout/layout-part/newmenu.vue

@@ -0,0 +1,116 @@
+<template lang="html">
+  <div id="sideMenu">
+    <div id="menuBox">
+      <el-col :span="24">
+        <el-menu :unique-opened="true">
+          <template v-for="item in menu">
+            <template v-if="!item.children">
+              <el-menu-item :index="item.path" @click="selectMenu(item.path)" :key="item.name">
+                <i v-if="item.icon" :class="item.icon"></i>
+                <span v-if="item.name" slot="title">{{ item.name }}</span>
+              </el-menu-item>
+            </template>
+
+            <el-submenu v-else :index="item.name || item.path" :key="item.name">
+              <template slot="title">
+                <i v-if="item && item.icon" :class="item.icon"></i>
+                <span v-if="item && item.name" slot="title">{{ item.name }}</span>
+              </template>
+              <template v-for="(child, childIndex) in item.children">
+                <div :key="childIndex" v-if="!child.hidden">
+                  <el-menu-item :index="item.path || '' + child.path" @click="selectMenu(item.path || '' + child.path)">
+                    <span v-if="child && child.name" slot="title">{{ child.name }}</span>
+                  </el-menu-item>
+                </div>
+              </template>
+            </el-submenu>
+          </template>
+        </el-menu>
+      </el-col>
+    </div>
+  </div>
+</template>
+
+<script>
+import {
+  index,
+  menu,
+  department,
+  permission,
+  adminUser,
+  business,
+  vip,
+  user,
+  duijiehui,
+  enterpriseProduct,
+  enterpriseTrans,
+  technical,
+  defaultMenu,
+} from '@/util/role_menu.js';
+import * as menus from '@/util/role_menu.js';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions } = createNamespacedHelpers('login');
+import _ from 'lodash';
+export default {
+  name: 'sideMenu',
+  components: {},
+  data() {
+    return {
+      menu: [],
+    };
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  created() {},
+  methods: {
+    ...mapActions(['toGetMenu', 'logout']),
+    async search() {
+      if (!this.user.uid) return;
+      if (this.user.role == '1') {
+        this.menu.push(
+          index,
+          menu,
+          department,
+          permission,
+          adminUser,
+          business,
+          vip,
+          user,
+          duijiehui,
+          enterpriseProduct,
+          enterpriseTrans,
+          technical,
+          defaultMenu
+        );
+        return;
+      }
+      const res = await this.toGetMenu({ id: this.user.uid });
+      if (this.$checkRes(res)) {
+        let menu = res.data.menus;
+        menu = menu.map(i => {
+          return { name: i.role_name, path: i.url };
+        });
+        let duplicate = JSON.parse(JSON.stringify(this.menu));
+        duplicate.push(...menu);
+        let nm = _.uniqBy(duplicate, 'path');
+        this.$set(this, `menu`, nm);
+      }
+    },
+
+    selectMenu(path) {
+      this.$router.push({ path: path });
+    },
+  },
+  watch: {
+    user: {
+      handler(val, oval) {
+        if (val && !_.isEqual(val, oval)) this.search();
+      },
+      immediate: true,
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 62 - 0
src/layout/main-layout.vue

@@ -0,0 +1,62 @@
+<template>
+  <div id="main-layout">
+    <el-container style="background:#e7e8eb;">
+      <el-header height="4rem" class="head">
+        <heads></heads>
+      </el-header>
+      <el-container class="contain">
+        <el-aside width="13rem" class="side">
+          <newmenu></newmenu>
+        </el-aside>
+        <el-main class="main">
+          <router-view />
+        </el-main>
+      </el-container>
+    </el-container>
+  </div>
+</template>
+
+<script>
+import heads from '@/layout/layout-part/heads.vue';
+import newmenu from '@/layout/layout-part/newmenu.vue';
+import { mapActions, mapState } from 'vuex';
+export default {
+  name: 'main-layout',
+  props: {},
+  components: {
+    newmenu,
+    heads,
+  },
+  data: () => ({}),
+  created() {},
+  computed: {},
+  methods: {},
+};
+</script>
+
+<style lang="less" scoped>
+.head {
+  margin: 0;
+  padding: 0;
+  width: 100%;
+  background: #fff;
+}
+.contain {
+  min-height: 670px;
+  margin: 20px 30px;
+  border: 1px solid #a2a2b6;
+  background: #eeeeee;
+}
+.side {
+  margin: 0;
+  padding: 0;
+  width: 2rem;
+  border-right: 1px solid #a2a2b6;
+  background: #ffffff;
+}
+.main {
+  margin: 0;
+  padding: 0;
+  background: #ffffff;
+}
+</style>

+ 10 - 2
src/router/index.js

@@ -1,18 +1,26 @@
 import Vue from 'vue';
 import VueRouter from 'vue-router';
+import checkLogin from '@common/router/before';
 
 Vue.use(VueRouter);
 
 const routes = [
   {
     path: '/',
-    name: '',
-    component: () => import('../views/index.vue'),
+    name: 'home',
+    component: () => import('../views/home/index.vue'),
   },
 ];
 
 const router = new VueRouter({
+  mode: 'history',
+  base: process.env.NODE_ENV === 'development' ? '' : process.env.VUE_APP_ROUTER,
   routes,
 });
+checkLogin(router, () => {
+  let url = process.env.NODE_ENV === 'development' ? null : `/platlive/login`;
+  if (url) window.location.href = url;
+  else console.log('开发环境自己弄');
+});
 
 export default router;

+ 8 - 3
src/store/index.js

@@ -1,11 +1,16 @@
 import Vue from 'vue';
 import Vuex from 'vuex';
+import login from '@common/store/login';
+import * as ustate from '@common/store/user/state';
+import * as umutations from '@common/store/user/mutations';
 
 Vue.use(Vuex);
 
 export default new Vuex.Store({
-  state: {},
-  mutations: {},
+  modules: {
+    login,
+  },
+  state: { ...ustate },
+  mutations: { ...umutations },
   actions: {},
-  modules: {},
 });

+ 29 - 0
src/store/user/mutations.js

@@ -0,0 +1,29 @@
+const jwt = require('jsonwebtoken');
+
+export const setUser = (state, payload) => {
+  let res = true;
+  //登陆时
+  if (payload) {
+    state.token = payload;
+    let user = jwt.decode(payload);
+    console.log(user);
+  } else {
+    //已经登陆,切换路由时取出用户信息放在总store中
+    let token = localStorage.getItem('token');
+    if (token) {
+      state.user = jwt.decode(token);
+    } else {
+      res = false;
+      state.user = undefined;
+      console.warn('用户未登录');
+    }
+  }
+  return res;
+};
+
+export const deleteUser = (state, payload) => {
+  state.user = {};
+  state.menuList = [];
+  localStorage.removeItem('user');
+  localStorage.removeItem('menuList');
+};

+ 2 - 0
src/store/user/state.js

@@ -0,0 +1,2 @@
+export const user = {};
+export const token = undefined;

+ 65 - 0
src/util/role_menu.js

@@ -0,0 +1,65 @@
+export const index = {
+  name: '首页',
+  path: '/',
+};
+export const menu = {
+  name: '菜单管理',
+  path: '/menu',
+};
+export const department = {
+  name: '部门管理',
+  path: '/department/index',
+};
+export const permission = {
+  name: '权限管理',
+  path: '/permission/index',
+};
+export const adminUser = {
+  name: '机构管理员',
+  path: '/adminUser',
+};
+export const business = {
+  name: '业务管理员',
+  path: '/business',
+};
+export const vip = {
+  name: 'vip用户',
+  path: '/vip/index',
+};
+export const user = {
+  name: '用户管理',
+  children: [
+    {
+      name: '个人&企业用户管理',
+      path: '/user/index',
+    },
+    {
+      name: '专家用户管理',
+      path: '/user/exportIndex',
+    },
+    {
+      name: '临时用户管理',
+      path: '/user/temporaryIndex',
+    },
+  ],
+};
+export const duijiehui = {
+  name: '对接会',
+  path: '/duijiehui/index',
+};
+export const enterpriseProduct = {
+  name: '科技超市商品审核管理',
+  path: '/enterpriseProduct/index',
+};
+export const enterpriseTrans = {
+  name: '科技超市交易状态审核管理',
+  path: '/enterpriseTrans/index',
+};
+export const technical = {
+  name: '技术培训',
+  path: '/technical/index',
+};
+export const defaultMenu = {
+  name: '平台字典管理',
+  path: '/dictionary',
+};

+ 0 - 2
src/views/index.vue

@@ -3,7 +3,6 @@
     <p>index</p>
   </div>
 </template>
-
 <script>
 export default {
   name: 'index',
@@ -15,5 +14,4 @@ export default {
   methods: {},
 };
 </script>
-
 <style lang="less" scoped></style>

+ 13 - 9
vue.config.js

@@ -1,7 +1,8 @@
 const path = require('path');
-const publics = path.resolve(__dirname, '../web-common');
+const common = path.resolve(__dirname, '../common');
 module.exports = {
   publicPath: process.env.NODE_ENV === 'development' ? '/' : process.env.VUE_APP_ROUTER,
+  // outputDir: process.env.VUE_APP_ROUTER,
   configureWebpack: config => {
     Object.assign(config, {
       // 开发生产共同配置
@@ -10,7 +11,7 @@ module.exports = {
           '@': path.resolve(__dirname, './src'),
           '@c': path.resolve(__dirname, './src/components'),
           '@a': path.resolve(__dirname, './src/assets'),
-          '@publics': publics,
+          '@common': common,
         },
       },
     });
@@ -19,15 +20,18 @@ module.exports = {
     port: '8001',
     //api地址前缀
     proxy: {
-      '/api': {
+      '/weixin': {
         target: 'http://smart.cc-lotus.info',
+        changeOrigin: true,
+        ws: true,
+      },
+      '/files': {
+        target: 'http://free.liaoningdoupo.com',
+      },
+      '/api': {
+        target: 'http://free.liaoningdoupo.com',
+        changeOrigin: true,
         ws: true,
-        onProxyReq(proxyReq, req, res) {
-          proxyReq.setHeader('x-tenant', '99991');
-        },
-        '/files': {
-          target: 'http://free.liaoningdoupo.com',
-        },
       },
     },
   },