lrf402788946 5 年之前
父节点
当前提交
490e8a3315

+ 37 - 0
.eslintrc.js

@@ -0,0 +1,37 @@
+// https://eslint.org/docs/user-guide/configuring
+
+module.exports = {
+  root: true,
+  env: {
+    node: true
+  },
+  extends: ["plugin:vue/essential", "@vue/prettier"],
+  plugins: ["vue"],
+  globals: {
+    '$': false,
+    'jquery': false
+  },
+  rules: {
+    "max-len": [
+      "warn",
+      {
+        code: 250
+      }
+    ],
+    "no-unused-vars": "off",
+    "no-console": "off",
+    "prettier/prettier": [
+      "warn",
+      {
+        singleQuote: true,
+        trailingComma: "es5",
+        bracketSpacing: true,
+        jsxBracketSameLine: true,
+        printWidth: 160,
+      }
+    ]
+  },
+  parserOptions: {
+    parser: "babel-eslint"
+  }
+};

+ 1 - 0
.gitignore

@@ -1,6 +1,7 @@
 .DS_Store
 node_modules
 /dist
+package-lock.json
 
 # local env files
 .env.local

+ 1 - 1
babel.config.js

@@ -1,3 +1,3 @@
 module.exports = {
-  presets: ["@vue/app"]
+  presets: ['@vue/app'],
 };

+ 3 - 0
package.json

@@ -9,7 +9,10 @@
   },
   "dependencies": {
     "core-js": "^2.6.5",
+    "element-ui": "^2.10.1",
+    "normalize.css": "^8.0.1",
     "vue": "^2.6.10",
+    "vue-meta": "^2.0.5",
     "vue-router": "^3.0.3",
     "vuex": "^3.0.1"
   },

+ 1 - 27
src/App.vue

@@ -1,29 +1,3 @@
 <template>
-  <div id="app">
-    <div id="nav">
-      <router-link to="/">Home</router-link> |
-      <router-link to="/about">About</router-link>
-    </div>
-    <router-view />
-  </div>
+  <router-view />
 </template>
-
-<style lang="scss">
-#app {
-  font-family: "Avenir", Helvetica, Arial, sans-serif;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-  text-align: center;
-  color: #2c3e50;
-}
-#nav {
-  padding: 30px;
-  a {
-    font-weight: bold;
-    color: #2c3e50;
-    &.router-link-exact-active {
-      color: #42b983;
-    }
-  }
-}
-</style>

二进制
src/assets/404.png


二进制
src/assets/404_cloud.png


二进制
src/assets/logo.png


二进制
src/assets/timg.jpg


+ 13 - 0
src/components/AppMain.vue

@@ -0,0 +1,13 @@
+<template>
+  <section class="app-main">
+    <transition name="el-fade-in-linear" mode="out-in">
+      <router-view></router-view>
+    </transition>
+  </section>
+</template>
+
+<script>
+export default {
+  name: 'AppMain',
+};
+</script>

+ 0 - 114
src/components/HelloWorld.vue

@@ -1,114 +0,0 @@
-<template>
-  <div class="hello">
-    <h1>{{ msg }}</h1>
-    <p>
-      For a guide and recipes on how to configure / customize this project,<br />
-      check out the
-      <a href="https://cli.vuejs.org" target="_blank" rel="noopener"
-        >vue-cli documentation</a
-      >.
-    </p>
-    <h3>Installed CLI Plugins</h3>
-    <ul>
-      <li>
-        <a
-          href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
-          target="_blank"
-          rel="noopener"
-          >babel</a
-        >
-      </li>
-      <li>
-        <a
-          href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
-          target="_blank"
-          rel="noopener"
-          >eslint</a
-        >
-      </li>
-    </ul>
-    <h3>Essential Links</h3>
-    <ul>
-      <li>
-        <a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
-      </li>
-      <li>
-        <a href="https://forum.vuejs.org" target="_blank" rel="noopener"
-          >Forum</a
-        >
-      </li>
-      <li>
-        <a href="https://chat.vuejs.org" target="_blank" rel="noopener"
-          >Community Chat</a
-        >
-      </li>
-      <li>
-        <a href="https://twitter.com/vuejs" target="_blank" rel="noopener"
-          >Twitter</a
-        >
-      </li>
-      <li>
-        <a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
-      </li>
-    </ul>
-    <h3>Ecosystem</h3>
-    <ul>
-      <li>
-        <a href="https://router.vuejs.org" target="_blank" rel="noopener"
-          >vue-router</a
-        >
-      </li>
-      <li>
-        <a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
-      </li>
-      <li>
-        <a
-          href="https://github.com/vuejs/vue-devtools#vue-devtools"
-          target="_blank"
-          rel="noopener"
-          >vue-devtools</a
-        >
-      </li>
-      <li>
-        <a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener"
-          >vue-loader</a
-        >
-      </li>
-      <li>
-        <a
-          href="https://github.com/vuejs/awesome-vue"
-          target="_blank"
-          rel="noopener"
-          >awesome-vue</a
-        >
-      </li>
-    </ul>
-  </div>
-</template>
-
-<script>
-export default {
-  name: "HelloWorld",
-  props: {
-    msg: String
-  }
-};
-</script>
-
-<!-- Add "scoped" attribute to limit CSS to this component only -->
-<style scoped lang="scss">
-h3 {
-  margin: 40px 0 0;
-}
-ul {
-  list-style-type: none;
-  padding: 0;
-}
-li {
-  display: inline-block;
-  margin: 0 10px;
-}
-a {
-  color: #42b983;
-}
-</style>

+ 104 - 0
src/components/NavBar.vue

@@ -0,0 +1,104 @@
+<template>
+  <el-menu class="navbar" mode="horizontal">
+    <div class="user-profile-container">
+      <div class="user-profile-content">
+        <div class="menu-icons">
+          <span class="menu-icon"><i class="el-icon-search icon"></i></span>
+          <span class="menu-icon"><i class="el-icon-message icon"></i></span>
+          <span class="menu-icon">
+            <el-badge is-dot class="item">
+              <i class="el-icon-bell icon"></i>
+            </el-badge>
+          </span>
+        </div>
+        <!-- <el-dropdown>
+          <div class="user-profile-body">
+            <img class="user-avatar" src="https://img.alicdn.com/tfs/TB1ONhloamWBuNjy1XaXXXCbXXa-200-200.png" />
+            <span class="user-name" v-if="isLogin">欢迎,{{ (user && user.user_name) || '' }}</span>
+            <span class="user-name" v-else @click="$router.push({ path: '/login' })">请登录</span>
+          </div>
+          <el-dropdown-menu class="user-dropdown" slot="dropdown">
+            <router-link to="/updatePw" v-if="isLogin">
+              <el-dropdown-item>
+                修改密码
+              </el-dropdown-item>
+            </router-link>
+            <el-dropdown-item v-if="isLogin">
+              <span @click="toLogout()" style="display:block;">退出</span>
+            </el-dropdown-item>
+          </el-dropdown-menu>
+        </el-dropdown> -->
+      </div>
+    </div>
+  </el-menu>
+</template>
+
+<script>
+export default {
+  name: 'NavBar',
+  computed: {},
+  data() {
+    return {
+      isLogin: false,
+    };
+  },
+  async created() {},
+  methods: {},
+};
+</script>
+
+<style lang="scss" scoped>
+.navbar {
+  height: 64px;
+  box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
+  .user-profile-container {
+    position: absolute;
+    right: 20px;
+    cursor: pointer;
+    .user-profile-content {
+      display: flex;
+      padding: 20px 0;
+    }
+    .menu-icons {
+      display: flex;
+      align-items: center;
+      .menu-icon {
+        padding: 0 12px;
+        .icon {
+          display: inline-block;
+          font-size: 18px;
+          text-align: center;
+        }
+      }
+    }
+    .user-profile-body {
+      position: relative;
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      justify-content: center;
+      text-align: center;
+      padding-right: 14px;
+    }
+    .user-avatar {
+      width: 24px;
+      height: 24px;
+      margin: 0 8px 0 12px;
+      border-radius: 4px;
+    }
+    .user-name {
+      color: rgba(0, 0, 0, 0.65);
+    }
+    .user-department {
+      font-size: 12px;
+      color: rgba(102, 102, 102, 0.65);
+    }
+    .el-icon-caret-bottom {
+      position: absolute;
+      right: 0;
+      top: 13px;
+      font-size: 12px;
+    }
+  }
+}
+</style>

+ 52 - 0
src/components/ScrollBar.vue

@@ -0,0 +1,52 @@
+<template>
+  <div class="scroll-container" ref="scrollContainer" @wheel.prevent="handleScroll">
+    <div class="scroll-wrapper" ref="scrollWrapper" :style="{ top: top + 'px' }">
+      <slot></slot>
+    </div>
+  </div>
+</template>
+
+<script>
+const delta = 15;
+
+export default {
+  name: 'ScrollBar',
+  data() {
+    return {
+      top: 0,
+    };
+  },
+  methods: {
+    handleScroll(e) {
+      const eventDelta = e.wheelDelta || -e.deltaY * 3;
+      const $container = this.$refs.scrollContainer;
+      const $containerHeight = $container.offsetHeight;
+      const $wrapper = this.$refs.scrollWrapper;
+      const $wrapperHeight = $wrapper.offsetHeight;
+      if (eventDelta > 0) {
+        this.top = Math.min(0, this.top + eventDelta);
+      } else if ($containerHeight - delta < $wrapperHeight) {
+        if (this.top < -($wrapperHeight - $containerHeight + delta)) {
+          this.top = this.top;
+        } else {
+          this.top = Math.max(this.top + eventDelta, $containerHeight - $wrapperHeight - delta);
+        }
+      } else {
+        this.top = 0;
+      }
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.scroll-container {
+  width: 100%;
+  height: 100%;
+  background-color: #00142a;
+  .scroll-wrapper {
+    position: absolute;
+    width: 100%;
+  }
+}
+</style>

+ 103 - 0
src/components/SideBar.vue

@@ -0,0 +1,103 @@
+<template>
+  <scroll-bar>
+    <div class="logo">
+      <img src="https://img.alicdn.com/tfs/TB13UQpnYGYBuNjy0FoXXciBFXa-242-134.png" width="40" />
+      <span class="site-name">ADMIN LITE</span>
+    </div>
+    <el-menu mode="vertical" :show-timeout="200" background-color="#00142a" text-color="hsla(0, 0%, 100%, .65)" active-text-color="#409EFF">
+      <el-submenu index="1">
+        <template slot="title">
+          <i class="el-icon-location"></i>
+          <span>导航一</span>
+        </template>
+        <el-menu-item-group>
+          <template slot="title">
+            分组一
+          </template>
+          <el-menu-item index="1-1">选项1</el-menu-item>
+          <el-menu-item index="1-2">选项2</el-menu-item>
+        </el-menu-item-group>
+        <el-menu-item-group title="分组2">
+          <el-menu-item index="1-3">选项3</el-menu-item>
+        </el-menu-item-group>
+        <el-submenu index="1-4">
+          <template slot="title">
+            选项4
+          </template>
+          <el-menu-item index="1-4-1">选项1</el-menu-item>
+        </el-submenu>
+      </el-submenu>
+    </el-menu>
+  </scroll-bar>
+</template>
+
+<script>
+import ScrollBar from './ScrollBar.vue';
+export default {
+  components: { ScrollBar },
+  name: 'SideBar',
+  props: {},
+  data() {
+    return {};
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.logo {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 64px;
+  line-height: 64px;
+  background: #002140;
+  color: #fff;
+  text-align: center;
+  font-size: 20px;
+  font-weight: 600;
+  overflow: hidden;
+}
+.site-name {
+  margin-left: 10px;
+}
+.sidebar-container {
+  box-shadow: 2px 0 6px rgba(0, 21, 41, 0.35);
+  transition: width 0.28s;
+  width: 256px !important;
+  height: 100%;
+  position: fixed;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1001;
+  overflow: hidden;
+  a {
+    display: inline-block;
+    width: 100%;
+  }
+  .el-menu {
+    padding-top: 16px;
+    width: 100% !important;
+    border: none;
+  }
+  .el-submenu .el-menu-item {
+    min-width: 256px !important;
+    padding-left: 48px !important;
+    background-color: #000c17 !important;
+    &:hover {
+      color: #fff !important;
+    }
+  }
+  .el-menu-item,
+  .el-submenu .el-menu-item {
+    &.is-active {
+      background-color: #188fff !important;
+      color: #fff !important;
+    }
+  }
+  .el-submenu__title i {
+    font-size: 16px;
+    color: rgba(255, 255, 255, 0.65);
+  }
+}
+</style>

+ 89 - 0
src/config/menuConfig.js

@@ -0,0 +1,89 @@
+// 菜单配置
+// headerMenuConfig:头部导航配置
+// asideMenuConfig:侧边导航配置
+
+const headerMenuConfig = [];
+
+const asideMenuConfig = [
+  {
+    path: '', //菜单母路由
+    name: 'Dashboard', //菜单母路由名称
+    icon: 'el-icon-menu', //菜单母路由图标
+    children: [
+      {
+        path: '/test', //子路由
+        name: '测试页', //子路由名称
+      },
+      {
+        path: '/404',
+        name: '404页',
+      },
+      {
+        path: '/workplace',
+        name: '工作台',
+      },
+    ],
+  },
+  {
+    path: '',
+    name: '系统管理',
+    icon: 'el-icon-setting',
+    children: [
+      {
+        path: '/dept',
+        name: '部门管理',
+      },
+      {
+        path: '/user',
+        name: '用户管理',
+      },
+      {
+        path: '/role',
+        name: '权限管理',
+      },
+      {
+        path: '/user_role',
+        name: '用户权限分配',
+      },
+    ],
+  },
+  {
+    path: '/enterprise',
+    name: '企业管理',
+    icon: 'el-icon-edit-outline',
+    children: [
+      {
+        path: '/check',
+        name: '企业发布与审核',
+      },
+    ],
+  },
+  {
+    path: '/product',
+    name: '产品管理',
+    icon: 'el-icon-present',
+    children: [
+      {
+        path: '/already',
+        name: '已发布产品',
+      },
+    ],
+  },
+  {
+    path: '/type',
+    name: '类别管理',
+    icon: 'el-icon-tickets',
+    children: [
+      {
+        path: '/productType',
+        name: '产品类别管理',
+      },
+      {
+        path: '/enterpriseType',
+        name: '企业类别管理 ',
+      },
+    ],
+  },
+];
+
+export { headerMenuConfig, asideMenuConfig };

+ 104 - 0
src/config/tableConfig.js

@@ -0,0 +1,104 @@
+//只有显示的字段放这里面,像不显示id的时候,不写这里面,如果需要用id,在自定义列中可以调用
+//变量名称以路由名称命名,如果涉及共用,手写(现阶段都是手写,之后改成提取路由作为参数筛选列表)
+const dept = [
+  {
+    prop: 'dept_name',
+    label: '部门名称',
+  },
+  {
+    prop: 'dept_duty',
+    label: '部门职责',
+  },
+  {
+    prop: 'dept_tell',
+    label: '部门电话',
+  },
+];
+const role = [
+  {
+    prop: 'role_code',
+    label: '权限代码',
+  },
+  {
+    prop: 'role_name',
+    label: '权限名称',
+  },
+];
+const user = [
+  {
+    prop: 'login_id',
+    label: '登录ID',
+  },
+  {
+    prop: 'user_name',
+    label: '用户名',
+  },
+  {
+    prop: 'phone',
+    label: '电话号码',
+  },
+  {
+    prop: 'addr',
+    label: '地址',
+  },
+  /**
+   * 所属部门需要筛选处理,在该视图中筛选,不作为直接输出项显示
+   * {
+      prop: 'dept_id',
+      label: '所属部门',
+     },
+   */
+];
+
+const user_role = [
+  {
+    prop: 'user_name',
+    label: '用户名',
+  },
+  /**
+ * 所属部门需要筛选处理,在该视图中筛选,不作为直接输出项显示
+ * {
+    prop: 'dept_id',
+    label: '所属部门',
+   },
+ */
+];
+
+const check = [
+  {
+    prop: 'name',
+    label: '企业名称',
+  },
+  {
+    prop: 'contact',
+    label: '联系方式',
+  },
+  {
+    prop: 'addr',
+    label: '地址',
+  },
+];
+
+const enterpriseType = [
+  {
+    prop: 'code',
+    label: '企业类别代码',
+  },
+  {
+    prop: 'name',
+    label: '企业类别名称',
+  },
+];
+
+const productType = [
+  {
+    prop: 'code',
+    label: '产品类别代码',
+  },
+  {
+    prop: 'name',
+    label: '产品类别名称',
+  },
+];
+
+export { dept, role, user, user_role, check, enterpriseType, productType };

+ 9 - 6
src/main.js

@@ -1,12 +1,15 @@
-import Vue from "vue";
-import App from "./App.vue";
-import router from "./router";
-import store from "./store";
+import Vue from 'vue';
+import App from './App.vue';
+import router from './router';
+import store from './store';
+import '@/plugins/element';
+import '@/plugins/meta';
+import 'normalize.css/normalize.css';
 
 Vue.config.productionTip = false;
 
 new Vue({
   router,
   store,
-  render: h => h(App)
-}).$mount("#app");
+  render: h => h(App),
+}).$mount('#app');

+ 5 - 0
src/plugins/element.js

@@ -0,0 +1,5 @@
+import Vue from 'vue';
+import Element from 'element-ui';
+import 'element-ui/lib/theme-chalk/index.css';
+
+Vue.use(Element);

+ 4 - 0
src/plugins/meta.js

@@ -0,0 +1,4 @@
+import Vue from 'vue';
+import Meta from 'vue-meta';
+
+Vue.use(Meta);

+ 18 - 16
src/router.js

@@ -1,26 +1,28 @@
-import Vue from "vue";
-import Router from "vue-router";
-import Home from "./views/Home.vue";
+import Vue from 'vue';
+import Router from 'vue-router';
 
 Vue.use(Router);
 
 export default new Router({
-  mode: "history",
+  mode: 'history',
   base: process.env.BASE_URL,
   routes: [
     {
-      path: "/",
-      name: "home",
-      component: Home
+      path: '/login',
+      name: 'login',
+      component: () => import('./views/login.vue'),
     },
     {
-      path: "/about",
-      name: "about",
-      // route level code-splitting
-      // this generates a separate chunk (about.[hash].js) for this route
-      // which is lazy-loaded when the route is visited.
-      component: () =>
-        import(/* webpackChunkName: "about" */ "./views/About.vue")
-    }
-  ]
+      path: '/',
+      name: 'index',
+      component: () => import('./views/index.vue'),
+      children: [
+        {
+          path: '/404',
+          name: 'notFound',
+          component: () => import('./views/NotFound.vue'),
+        },
+      ],
+    },
+  ],
 });

+ 3 - 3
src/store.js

@@ -1,10 +1,10 @@
-import Vue from "vue";
-import Vuex from "vuex";
+import Vue from 'vue';
+import Vuex from 'vuex';
 
 Vue.use(Vuex);
 
 export default new Vuex.Store({
   state: {},
   mutations: {},
-  actions: {}
+  actions: {},
 });

+ 0 - 5
src/views/About.vue

@@ -1,5 +0,0 @@
-<template>
-  <div class="about">
-    <h1>This is an about page</h1>
-  </div>
-</template>

+ 0 - 18
src/views/Home.vue

@@ -1,18 +0,0 @@
-<template>
-  <div class="home">
-    <img alt="Vue logo" src="../assets/logo.png" />
-    <HelloWorld msg="Welcome to Your Vue.js App" />
-  </div>
-</template>
-
-<script>
-// @ is an alias to /src
-import HelloWorld from "@/components/HelloWorld.vue";
-
-export default {
-  name: "home",
-  components: {
-    HelloWorld
-  }
-};
-</script>

+ 222 - 0
src/views/NotFound.vue

@@ -0,0 +1,222 @@
+<template>
+  <div style="background:#f0f2f5;margin-top: -20px;height:100%;">
+    <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="exception">
+        <div class="exception__headline">抱歉,你访问的页面不存在</div>
+        <a href="/" class="exception__return-home">返回首页</a>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import img_404 from '@/assets/404.png';
+import img_404_cloud from '@/assets/404_cloud.png';
+
+export default {
+  name: 'page404',
+  data() {
+    return {
+      img_404,
+      img_404_cloud,
+    };
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.wscn-http404 {
+  display: flex;
+  align-items: center;
+  position: relative;
+  margin: 20px auto 60px;
+  padding: 0 100px;
+  overflow: hidden;
+  .pic-404 {
+    position: relative;
+    float: left;
+    width: 600px;
+    padding: 150px 0;
+    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;
+        }
+      }
+    }
+  }
+  .exception {
+    position: relative;
+    float: left;
+    width: 300px;
+    padding: 150px 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: #434e59;
+      opacity: 0;
+      margin-bottom: 20px;
+      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>

+ 44 - 0
src/views/index.vue

@@ -0,0 +1,44 @@
+<template>
+  <div class="app-wrapper">
+    <side-bar class="sidebar-container"></side-bar>
+    <div class="main-container">
+      <nav-bar></nav-bar>
+      <app-main></app-main>
+    </div>
+  </div>
+</template>
+
+<script>
+import NavBar from '@/components/NavBar.vue';
+import SideBar from '@/components/SideBar.vue';
+import AppMain from '@/components/AppMain.vue';
+
+export default {
+  name: 'layout',
+  components: {
+    NavBar,
+    SideBar,
+    AppMain,
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.app-wrapper {
+  position: relative;
+  height: 100%;
+  width: 100%;
+  &:after {
+    content: '';
+    display: table;
+    clear: both;
+  }
+}
+
+.main-container {
+  min-height: 100vh;
+  transition: margin-left 0.28s;
+  margin-left: 256px;
+  background-color: #f0f2f5;
+}
+</style>

+ 109 - 0
src/views/login.vue

@@ -0,0 +1,109 @@
+<template lang="html">
+  <div id="login">
+    <body :style="'overflow-y: auto;background-image: url(' + img.bg + '); background-repeat:no-repeat; background-size:auto;'">
+      <div class="page-container">
+        <div>
+          <h1 style="letter-spacing:4px; padding-bottom:20px; font-weight:bold; color:#fff;">科技厅中台系统</h1>
+        </div>
+        <el-form :model="form" :rules="rules" ref="form" style="background:#ffffff;padding:5% 2%;" class="row">
+          <el-row>
+            <el-col :span="24" style="margin-top:3%;">
+              <el-form-item prop="login_id">
+                <el-col :span="6" style="font-weight: 600;font-size: 18px;">用户名</el-col>
+                <el-col :span="15"><el-input v-model="form.login_id"></el-input></el-col>
+              </el-form-item>
+              <el-form-item prop="password">
+                <el-col :span="6" style="font-weight: 600;font-size: 18px;">密码</el-col>
+                <el-col :span="15"><el-input v-model="form.password" type="password" @keyup.enter.native="toLogin()"></el-input></el-col>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24" style="margin-bottom:5%;">
+              <el-col :span="4">&nbsp;</el-col>
+              <el-col :span="16">
+                <el-button type="primary" style="width:300px;font-size:16px;" @click="toLogin()">
+                  登&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;录
+                </el-button>
+              </el-col>
+              <el-col :span="4">&nbsp;</el-col>
+            </el-col>
+            <el-col :span="24" style="margin-bottom:5%;">
+              <el-col :span="4">&nbsp;</el-col>
+              <el-col :span="16">
+                <el-button type="info" style="width:300px;font-size:16px;" @click="closeAlert()">重&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;置</el-button>
+              </el-col>
+              <el-col :span="4">&nbsp;</el-col>
+            </el-col>
+          </el-row>
+        </el-form>
+      </div>
+    </body>
+  </div>
+</template>
+
+<script>
+import { mapActions, mapState } from 'vuex';
+export default {
+  name: 'login',
+  components: {},
+  data() {
+    return {
+      img: {
+        bg: require('@/assets/timg.jpg'),
+      },
+      form: {},
+      rules: {
+        name: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
+        pw: [{ required: true, message: '请输入密码', trigger: 'blur' }],
+      },
+    };
+  },
+  computed: {},
+  methods: {
+    ...mapActions(['login']),
+    async toLogin() {
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          this.operation();
+        } else {
+          console.log('error submit!!');
+          return false;
+        }
+      });
+    },
+    async operation() {
+      let { result } = await this.login({ data: this.form });
+      console.log(result);
+      if (result) this.$router.push({ path: '/' });
+    },
+    closeAlert() {
+      this.$refs.form.resetFields();
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+body {
+  width: 100vw;
+  height: 100vh;
+}
+.page-container {
+  /* logn-圆角	 */
+  margin: 0 auto;
+  width: 500px;
+  height: 450px;
+  text-align: center;
+  margin-top: 220px;
+}
+.row {
+  border-radius: 15px;
+  .el-form-item__error {
+    color: #f56c6c;
+    font-size: 12px;
+    line-height: 1;
+    padding-top: 4px;
+    position: absolute;
+    left: 7%;
+  }
+}
+</style>

+ 34 - 0
vue.config.js

@@ -0,0 +1,34 @@
+const path = require('path');
+
+module.exports = {
+  publicPath: process.env.NODE_ENV === 'production' ? '/kjtAdmin/' : './',
+  // pages: {
+  //   index: 'src/pages/login/main.js',
+  // },
+  configureWebpack: config => {
+    Object.assign(config, {
+      // 开发生产共同配置
+      resolve: {
+        alias: {
+          '@': path.resolve(__dirname, './src'),
+          '@c': path.resolve(__dirname, './src/components'),
+          '@a': path.resolve(__dirname, './src/assets'),
+        },
+      },
+    });
+  },
+  devServer: {
+    port: '8001',
+    //api地址前缀
+    proxy: {
+      '/admin': {
+        target: 'http://10.16.11.186:80', //10.16.11.186:80  10.16.11.227:7001
+        changeOrigin: true,
+        ws: false,
+        // pathRewrite: {
+        //   '/': '',
+        // },
+      },
+    },
+  },
+};