Commit 6a735f15a7a105a4176fbece3cac0036c65438ae

Authored by Adam
Exists in master

Merge branch 'master' into 'master'

Master

See merge request !3
... ... @@ -167,6 +167,7 @@ module.exports = {
167 167 'allowTemplateLiterals': true
168 168 }],
169 169 'semi': [2, 'never'],
  170 + // 'semi': 0,
170 171 'semi-spacing': [2, {
171 172 'before': false,
172 173 'after': true
... ...
  1 +// module.exports = {
  2 +// presets: [
  3 +// '@vue/app'
  4 +// ]
  5 +// }
  6 + // "@babel/preset-env",
  7 + // {
  8 + // "modules": false
  9 + // },
1 10 module.exports = {
2   - presets: [
3   - '@vue/app'
  11 + "presets": [
  12 + [
  13 + '@vue/app',
  14 + // '@babel/preset-env',
  15 + {
  16 + // "modules": false,
  17 + // "targets": { // 配置代码的运行环境
  18 + // "chrome": 64
  19 + // },
  20 + // "useBuiltIns": true // 开启对 babel-polyfill 的优化
  21 + }
  22 + ]
  23 + ],
  24 + "plugins": [
  25 + [
  26 + "component",
  27 + {
  28 + "libraryName": "element-ui",
  29 + "styleLibraryName": "theme-chalk"
  30 + }
  31 + ]
4 32 ]
5 33 }
... ...
1 1 import Mock from 'mockjs'
2   -import { param2Obj } from '../src/utils'
  2 +import {
  3 + param2Obj
  4 +} from '../src/utils'
3 5  
4 6 import user from './user'
5 7 import table from './table'
... ... @@ -16,7 +18,7 @@ export function mockXHR() {
16 18 // mock patch
17 19 // https://github.com/nuysoft/Mock/issues/300
18 20 Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
19   - Mock.XHR.prototype.send = function() {
  21 + Mock.XHR.prototype.send = function () {
20 22 if (this.custom.xhr) {
21 23 this.custom.xhr.withCredentials = this.withCredentials || false
22 24  
... ... @@ -28,10 +30,14 @@ export function mockXHR() {
28 30 }
29 31  
30 32 function XHR2ExpressReqWrap(respond) {
31   - return function(options) {
  33 + return function (options) {
32 34 let result = null
33 35 if (respond instanceof Function) {
34   - const { body, type, url } = options
  36 + const {
  37 + body,
  38 + type,
  39 + url
  40 + } = options
35 41 // https://expressjs.com/en/4x/api.html#req
36 42 result = respond({
37 43 method: type,
... ...
... ... @@ -3,11 +3,13 @@ import Mock from 'mockjs'
3 3 const data = Mock.mock({
4 4 'items|10': [{
5 5 id: '@id',
6   - title: '@sentence(3, 10)',
  6 + title: '@sentence(10, 10)',
7 7 'status|1': ['published', 'draft', 'deleted'],
8   - author: 'name@integer(300, 5000)',
9   - display_time: '@datetime',
10   - pageviews: '@integer(300, 5000)'
  8 + username: '@sentence(1, 2)',
  9 + create_at: '@datetime',
  10 + pageviews: '@integer(10, 500)',
  11 + openid: '@sentence(1, 1)',
  12 + avatar:'----'
11 13 }]
12 14 })
13 15  
... ...
... ... @@ -16,6 +16,7 @@
16 16 },
17 17 "dependencies": {
18 18 "axios": "0.18.1",
  19 + "babel-polyfill": "^6.26.0",
19 20 "echarts": "^4.7.0",
20 21 "element-ui": "2.13.0",
21 22 "js-cookie": "2.2.0",
... ... @@ -29,6 +30,7 @@
29 30 },
30 31 "devDependencies": {
31 32 "@babel/core": "7.0.0",
  33 + "@babel/preset-env": "^7.9.6",
32 34 "@babel/register": "7.0.0",
33 35 "@vue/cli-plugin-babel": "3.6.0",
34 36 "@vue/cli-plugin-eslint": "^3.9.1",
... ... @@ -36,9 +38,12 @@
36 38 "@vue/cli-service": "3.6.0",
37 39 "@vue/test-utils": "1.0.0-beta.29",
38 40 "autoprefixer": "^9.5.1",
  41 + "babel-cli": "^6.26.0",
39 42 "babel-core": "7.0.0-bridge.0",
40 43 "babel-eslint": "10.0.1",
41 44 "babel-jest": "23.6.0",
  45 + "babel-plugin-component": "^1.1.1",
  46 + "babel-preset-env": "^1.7.0",
42 47 "chalk": "2.4.2",
43 48 "connect": "3.6.6",
44 49 "eslint": "5.15.3",
... ... @@ -53,6 +58,7 @@
53 58 "serve-static": "^1.13.2",
54 59 "svg-sprite-loader": "4.1.3",
55 60 "svgo": "1.2.2",
  61 + "vue-schart": "^2.0.0",
56 62 "vue-template-compiler": "2.6.10"
57 63 },
58 64 "engines": {
... ...
1   -import request from '@/utils/request'
2   -
3   -export function login(data) {
4   - console.log('login....', data)
5   - return request({
6   - url: '/yp/user/login',
7   - method: 'post',
8   - data
9   - })
10   -}
11   -
12   -export function getInfo(token) {
13   - console.log('getInfo....', token)
14   - return request({
15   - url: '/yp/user/info',
16   - method: 'get',
17   - params: { token }
18   - })
19   -}
20   -
21   -export function logout() {
22   - console.log('logout....')
23   - return request({
24   - url: '/yp/user/logout',
25   - method: 'post'
26   - })
27   -}
  1 +// import request from '@/utils/request'
... ...
... ... @@ -0,0 +1,33 @@
  1 +import request from '@/utils/request'
  2 +
  3 +export function listMeta(params) {
  4 + return request({
  5 + url: '/yp/meta/list',
  6 + method: 'get',
  7 + params
  8 + })
  9 +}
  10 +
  11 +export function addMeta(params) {
  12 + return request({
  13 + url: '/yp/meta/add',
  14 + method: 'get',
  15 + params
  16 + })
  17 +}
  18 +
  19 +export function delMeta(params) {
  20 + return request({
  21 + url: '/yp/meta/del',
  22 + method: 'get',
  23 + params
  24 + })
  25 +}
  26 +
  27 +export function modiMeta(params) {
  28 + return request({
  29 + url: '/yp/meta/modi',
  30 + method: 'get',
  31 + params
  32 + })
  33 +}
... ...
src/api/relation.js
... ... @@ -0,0 +1,17 @@
  1 +import request from '@/utils/request'
  2 +
  3 +export function build(params) {
  4 + return request({
  5 + url: '/yp/relation/build',
  6 + method: 'get',
  7 + params
  8 + })
  9 +}
  10 +
  11 +export function del(params) {
  12 + return request({
  13 + url: '/yp/relation/del',
  14 + method: 'get',
  15 + params
  16 + })
  17 +}
... ...
... ... @@ -27,6 +27,24 @@ export function list(token) {
27 27 })
28 28 }
29 29  
  30 +export function add(token) {
  31 + console.log('addUser....', token)
  32 + return request({
  33 + url: '/yp/user/add',
  34 + method: 'get',
  35 + params: { token }
  36 + })
  37 +}
  38 +
  39 +export function modi(token) {
  40 + console.log('modiUser....', token)
  41 + return request({
  42 + url: '/yp/user/modi',
  43 + method: 'get',
  44 + params: { token }
  45 + })
  46 +}
  47 +
30 48 export function logout() {
31 49 console.log('logout....')
32 50 return request({
... ...
src/assets/img/img.jpg

6 KB

src/assets/img/login-bg.jpg

68.9 KB

src/common/Header.vue
... ... @@ -0,0 +1,191 @@
  1 +<template>
  2 + <div class="header">
  3 + <!-- 折叠按钮 -->
  4 + <div class="collapse-btn" @click="collapseChage">
  5 + <i v-if="!collapse" class="el-icon-s-fold"></i>
  6 + <i v-else class="el-icon-s-unfold"></i>
  7 + </div>
  8 + <div class="logo">后台管理系统</div>
  9 + <div class="header-right">
  10 + <div class="header-user-con">
  11 + <!-- 全屏显示 -->
  12 + <div class="btn-fullscreen" @click="handleFullScreen">
  13 + <el-tooltip effect="dark" :content="fullscreen?`取消全屏`:`全屏`" placement="bottom">
  14 + <i class="el-icon-rank"></i>
  15 + </el-tooltip>
  16 + </div>
  17 + <!-- 消息中心 -->
  18 + <div class="btn-bell">
  19 + <el-tooltip
  20 + effect="dark"
  21 + :content="message?`有${message}条未读消息`:`消息中心`"
  22 + placement="bottom"
  23 + >
  24 + <router-link to="/tabs">
  25 + <i class="el-icon-bell"></i>
  26 + </router-link>
  27 + </el-tooltip>
  28 + <span class="btn-bell-badge" v-if="message"></span>
  29 + </div>
  30 + <!-- 用户头像 -->
  31 + <div class="user-avator">
  32 + <img src="../assets/img/img.jpg" />
  33 + </div>
  34 + <!-- 用户名下拉菜单 -->
  35 + <el-dropdown class="user-name" trigger="click" @command="handleCommand">
  36 + <span class="el-dropdown-link">
  37 + {{username}}
  38 + <i class="el-icon-caret-bottom"></i>
  39 + </span>
  40 + <el-dropdown-menu slot="dropdown">
  41 + <a href="https://github.com/lin-xin/vue-manage-system" target="_blank">
  42 + <el-dropdown-item>项目仓库</el-dropdown-item>
  43 + </a>
  44 + <el-dropdown-item divided command="loginout">退出登录</el-dropdown-item>
  45 + </el-dropdown-menu>
  46 + </el-dropdown>
  47 + </div>
  48 + </div>
  49 + </div>
  50 +</template>
  51 +<script>
  52 +import bus from './bus';
  53 +export default {
  54 + data() {
  55 + return {
  56 + collapse: false,
  57 + fullscreen: false,
  58 + name: 'linxin',
  59 + message: 2
  60 + };
  61 + },
  62 + computed: {
  63 + username() {
  64 + let username = localStorage.getItem('ms_username');
  65 + return username ? username : this.name;
  66 + }
  67 + },
  68 + methods: {
  69 + // 用户名下拉菜单选择事件
  70 + handleCommand(command) {
  71 + if (command == 'loginout') {
  72 + localStorage.removeItem('ms_username');
  73 + this.$router.push('/login');
  74 + }
  75 + },
  76 + // 侧边栏折叠
  77 + collapseChage() {
  78 + this.collapse = !this.collapse;
  79 + bus.$emit('collapse', this.collapse);
  80 + },
  81 + // 全屏事件
  82 + handleFullScreen() {
  83 + let element = document.documentElement;
  84 + if (this.fullscreen) {
  85 + if (document.exitFullscreen) {
  86 + document.exitFullscreen();
  87 + } else if (document.webkitCancelFullScreen) {
  88 + document.webkitCancelFullScreen();
  89 + } else if (document.mozCancelFullScreen) {
  90 + document.mozCancelFullScreen();
  91 + } else if (document.msExitFullscreen) {
  92 + document.msExitFullscreen();
  93 + }
  94 + } else {
  95 + if (element.requestFullscreen) {
  96 + element.requestFullscreen();
  97 + } else if (element.webkitRequestFullScreen) {
  98 + element.webkitRequestFullScreen();
  99 + } else if (element.mozRequestFullScreen) {
  100 + element.mozRequestFullScreen();
  101 + } else if (element.msRequestFullscreen) {
  102 + // IE11
  103 + element.msRequestFullscreen();
  104 + }
  105 + }
  106 + this.fullscreen = !this.fullscreen;
  107 + }
  108 + },
  109 + mounted() {
  110 + if (document.body.clientWidth < 1500) {
  111 + this.collapseChage();
  112 + }
  113 + }
  114 +};
  115 +</script>
  116 +<style scoped>
  117 +.header {
  118 + position: relative;
  119 + box-sizing: border-box;
  120 + width: 100%;
  121 + height: 70px;
  122 + font-size: 22px;
  123 + color: #fff;
  124 +}
  125 +.collapse-btn {
  126 + float: left;
  127 + padding: 0 21px;
  128 + cursor: pointer;
  129 + line-height: 70px;
  130 +}
  131 +.header .logo {
  132 + float: left;
  133 + width: 250px;
  134 + line-height: 70px;
  135 +}
  136 +.header-right {
  137 + float: right;
  138 + padding-right: 50px;
  139 +}
  140 +.header-user-con {
  141 + display: flex;
  142 + height: 70px;
  143 + align-items: center;
  144 +}
  145 +.btn-fullscreen {
  146 + transform: rotate(45deg);
  147 + margin-right: 5px;
  148 + font-size: 24px;
  149 +}
  150 +.btn-bell,
  151 +.btn-fullscreen {
  152 + position: relative;
  153 + width: 30px;
  154 + height: 30px;
  155 + text-align: center;
  156 + border-radius: 15px;
  157 + cursor: pointer;
  158 +}
  159 +.btn-bell-badge {
  160 + position: absolute;
  161 + right: 0;
  162 + top: -2px;
  163 + width: 8px;
  164 + height: 8px;
  165 + border-radius: 4px;
  166 + background: #f56c6c;
  167 + color: #fff;
  168 +}
  169 +.btn-bell .el-icon-bell {
  170 + color: #fff;
  171 +}
  172 +.user-name {
  173 + margin-left: 10px;
  174 +}
  175 +.user-avator {
  176 + margin-left: 20px;
  177 +}
  178 +.user-avator img {
  179 + display: block;
  180 + width: 40px;
  181 + height: 40px;
  182 + border-radius: 50%;
  183 +}
  184 +.el-dropdown-link {
  185 + color: #fff;
  186 + cursor: pointer;
  187 +}
  188 +.el-dropdown-menu__item {
  189 + text-align: center;
  190 +}
  191 +</style>
0 192 \ No newline at end of file
... ...
src/common/Home.vue
... ... @@ -0,0 +1,50 @@
  1 +<template>
  2 + <div class="wrapper">
  3 + <v-head></v-head>
  4 + <v-sidebar></v-sidebar>
  5 + <div class="content-box" :class="{'content-collapse':collapse}">
  6 + <v-tags></v-tags>
  7 + <div class="content">
  8 + <transition name="move" mode="out-in">
  9 + <keep-alive :include="tagsList">
  10 + <router-view></router-view>
  11 + </keep-alive>
  12 + </transition>
  13 + <el-backtop target=".content"></el-backtop>
  14 + </div>
  15 + </div>
  16 + </div>
  17 +</template>
  18 +
  19 +<script>
  20 +import vHead from './Header.vue';
  21 +import vSidebar from './Sidebar.vue';
  22 +import vTags from './Tags.vue';
  23 +import bus from './bus';
  24 +export default {
  25 + data() {
  26 + return {
  27 + tagsList: [],
  28 + collapse: false
  29 + };
  30 + },
  31 + components: {
  32 + vHead,
  33 + vSidebar,
  34 + vTags
  35 + },
  36 + created() {
  37 + bus.$on('collapse-content', msg => {
  38 + this.collapse = msg;
  39 + });
  40 + // 只有在标签页列表里的页面才使用keep-alive,即关闭标签之后就不保存到内存中了。
  41 + bus.$on('tags', msg => {
  42 + let arr = [];
  43 + for (let i = 0, len = msg.length; i < len; i++) {
  44 + msg[i].name && arr.push(msg[i].name);
  45 + }
  46 + this.tagsList = arr;
  47 + });
  48 + }
  49 +};
  50 +</script>
0 51 \ No newline at end of file
... ...
src/common/Sidebar.vue
... ... @@ -0,0 +1,189 @@
  1 +<template>
  2 + <div class="sidebar">
  3 + <el-menu
  4 + class="sidebar-el-menu"
  5 + :default-active="onRoutes"
  6 + :collapse="collapse"
  7 + background-color="#324157"
  8 + text-color="#bfcbd9"
  9 + active-text-color="#20a0ff"
  10 + unique-opened
  11 + router
  12 + >
  13 + <template v-for="item in items">
  14 + <template v-if="item.subs">
  15 + <el-submenu :index="item.index" :key="item.index">
  16 + <template slot="title">
  17 + <i :class="item.icon"></i>
  18 + <span slot="title">{{ item.title }}</span>
  19 + </template>
  20 + <template v-for="subItem in item.subs">
  21 + <el-submenu
  22 + v-if="subItem.subs"
  23 + :index="subItem.index"
  24 + :key="subItem.index"
  25 + >
  26 + <template slot="title">{{ subItem.title }}</template>
  27 + <el-menu-item
  28 + v-for="(threeItem,i) in subItem.subs"
  29 + :key="i"
  30 + :index="threeItem.index"
  31 + >{{ threeItem.title }}</el-menu-item>
  32 + </el-submenu>
  33 + <el-menu-item
  34 + v-else
  35 + :index="subItem.index"
  36 + :key="subItem.index"
  37 + >{{ subItem.title }}</el-menu-item>
  38 + </template>
  39 + </el-submenu>
  40 + </template>
  41 + <template v-else>
  42 + <el-menu-item :index="item.index" :key="item.index">
  43 + <i :class="item.icon"></i>
  44 + <span slot="title">{{ item.title }}</span>
  45 + </el-menu-item>
  46 + </template>
  47 + </template>
  48 + </el-menu>
  49 + </div>
  50 +</template>
  51 +
  52 +<script>
  53 +import bus from './bus';
  54 +export default {
  55 + data() {
  56 + return {
  57 + collapse: false,
  58 + items: [
  59 + {
  60 + icon: 'el-icon-lx-home',
  61 + index: 'dashboard',
  62 + title: '系统首页'
  63 + },
  64 + {
  65 + icon: 'el-icon-lx-cascades',
  66 + index: 'table',
  67 + title: '基础表格'
  68 + },
  69 + {
  70 + icon: 'el-icon-lx-copy',
  71 + index: 'tabs',
  72 + title: 'tab选项卡'
  73 + },
  74 + {
  75 + icon: 'el-icon-lx-calendar',
  76 + index: '3',
  77 + title: '表单相关',
  78 + subs: [
  79 + {
  80 + index: 'form',
  81 + title: '基本表单'
  82 + },
  83 + {
  84 + index: '3-2',
  85 + title: '三级菜单',
  86 + subs: [
  87 + {
  88 + index: 'editor',
  89 + title: '富文本编辑器'
  90 + },
  91 + {
  92 + index: 'markdown',
  93 + title: 'markdown编辑器'
  94 + }
  95 + ]
  96 + },
  97 + {
  98 + index: 'upload',
  99 + title: '文件上传'
  100 + }
  101 + ]
  102 + },
  103 + {
  104 + icon: 'el-icon-lx-emoji',
  105 + index: 'icon',
  106 + title: '自定义图标'
  107 + },
  108 + {
  109 + icon: 'el-icon-pie-chart',
  110 + index: 'charts',
  111 + title: 'schart图表'
  112 + },
  113 + {
  114 + icon: 'el-icon-rank',
  115 + index: '6',
  116 + title: '拖拽组件',
  117 + subs: [
  118 + {
  119 + index: 'drag',
  120 + title: '拖拽列表'
  121 + },
  122 + {
  123 + index: 'dialog',
  124 + title: '拖拽弹框'
  125 + }
  126 + ]
  127 + },
  128 + {
  129 + icon: 'el-icon-lx-global',
  130 + index: 'i18n',
  131 + title: '国际化功能'
  132 + },
  133 + {
  134 + icon: 'el-icon-lx-warn',
  135 + index: '7',
  136 + title: '错误处理',
  137 + subs: [
  138 + {
  139 + index: 'permission',
  140 + title: '权限测试'
  141 + },
  142 + {
  143 + index: '404',
  144 + title: '404页面'
  145 + }
  146 + ]
  147 + },
  148 + {
  149 + icon: 'el-icon-lx-redpacket_fill',
  150 + index: '/donate',
  151 + title: '支持作者'
  152 + }
  153 + ]
  154 + };
  155 + },
  156 + computed: {
  157 + onRoutes() {
  158 + return this.$route.path.replace('/', '');
  159 + }
  160 + },
  161 + created() {
  162 + // 通过 Event Bus 进行组件间通信,来折叠侧边栏
  163 + bus.$on('collapse', msg => {
  164 + this.collapse = msg;
  165 + bus.$emit('collapse-content', msg);
  166 + });
  167 + }
  168 +};
  169 +</script>
  170 +
  171 +<style scoped>
  172 +.sidebar {
  173 + display: block;
  174 + position: absolute;
  175 + left: 0;
  176 + top: 70px;
  177 + bottom: 0;
  178 + overflow-y: scroll;
  179 +}
  180 +.sidebar::-webkit-scrollbar {
  181 + width: 0;
  182 +}
  183 +.sidebar-el-menu:not(.el-menu--collapse) {
  184 + width: 250px;
  185 +}
  186 +.sidebar > ul {
  187 + height: 100%;
  188 +}
  189 +</style>
0 190 \ No newline at end of file
... ...
src/common/Tags.vue
... ... @@ -0,0 +1,177 @@
  1 +<template>
  2 + <div class="tags" v-if="showTags">
  3 + <ul>
  4 + <li class="tags-li" v-for="(item,index) in tagsList" :class="{'active': isActive(item.path)}" :key="index">
  5 + <router-link :to="item.path" class="tags-li-title">
  6 + {{item.title}}
  7 + </router-link>
  8 + <span class="tags-li-icon" @click="closeTags(index)"><i class="el-icon-close"></i></span>
  9 + </li>
  10 + </ul>
  11 + <div class="tags-close-box">
  12 + <el-dropdown @command="handleTags">
  13 + <el-button size="mini" type="primary">
  14 + 标签选项<i class="el-icon-arrow-down el-icon--right"></i>
  15 + </el-button>
  16 + <el-dropdown-menu size="small" slot="dropdown">
  17 + <el-dropdown-item command="other">关闭其他</el-dropdown-item>
  18 + <el-dropdown-item command="all">关闭所有</el-dropdown-item>
  19 + </el-dropdown-menu>
  20 + </el-dropdown>
  21 + </div>
  22 + </div>
  23 +</template>
  24 +
  25 +<script>
  26 + import bus from './bus';
  27 + export default {
  28 + data() {
  29 + return {
  30 + tagsList: []
  31 + }
  32 + },
  33 + methods: {
  34 + isActive(path) {
  35 + return path === this.$route.fullPath;
  36 + },
  37 + // 关闭单个标签
  38 + closeTags(index) {
  39 + const delItem = this.tagsList.splice(index, 1)[0];
  40 + const item = this.tagsList[index] ? this.tagsList[index] : this.tagsList[index - 1];
  41 + if (item) {
  42 + delItem.path === this.$route.fullPath && this.$router.push(item.path);
  43 + }else{
  44 + this.$router.push('/');
  45 + }
  46 + },
  47 + // 关闭全部标签
  48 + closeAll(){
  49 + this.tagsList = [];
  50 + this.$router.push('/');
  51 + },
  52 + // 关闭其他标签
  53 + closeOther(){
  54 + const curItem = this.tagsList.filter(item => {
  55 + return item.path === this.$route.fullPath;
  56 + })
  57 + this.tagsList = curItem;
  58 + },
  59 + // 设置标签
  60 + setTags(route){
  61 + const isExist = this.tagsList.some(item => {
  62 + return item.path === route.fullPath;
  63 + })
  64 + if(!isExist){
  65 + if(this.tagsList.length >= 8){
  66 + this.tagsList.shift();
  67 + }
  68 + this.tagsList.push({
  69 + title: route.meta.title,
  70 + path: route.fullPath,
  71 + name: route.matched[1].components.default.name
  72 + })
  73 + }
  74 + bus.$emit('tags', this.tagsList);
  75 + },
  76 + handleTags(command){
  77 + command === 'other' ? this.closeOther() : this.closeAll();
  78 + }
  79 + },
  80 + computed: {
  81 + showTags() {
  82 + return this.tagsList.length > 0;
  83 + }
  84 + },
  85 + watch:{
  86 + $route(newValue, oldValue){
  87 + this.setTags(newValue);
  88 + }
  89 + },
  90 + created(){
  91 + this.setTags(this.$route);
  92 + // 监听关闭当前页面的标签页
  93 + bus.$on('close_current_tags', () => {
  94 + for (let i = 0, len = this.tagsList.length; i < len; i++) {
  95 + const item = this.tagsList[i];
  96 + if(item.path === this.$route.fullPath){
  97 + if(i < len - 1){
  98 + this.$router.push(this.tagsList[i+1].path);
  99 + }else if(i > 0){
  100 + this.$router.push(this.tagsList[i-1].path);
  101 + }else{
  102 + this.$router.push('/');
  103 + }
  104 + this.tagsList.splice(i, 1);
  105 + break;
  106 + }
  107 + }
  108 + })
  109 + }
  110 + }
  111 +</script>
  112 +
  113 +
  114 +<style>
  115 + .tags {
  116 + position: relative;
  117 + height: 30px;
  118 + overflow: hidden;
  119 + background: #fff;
  120 + padding-right: 120px;
  121 + box-shadow: 0 5px 10px #ddd;
  122 + }
  123 + .tags ul {
  124 + box-sizing: border-box;
  125 + width: 100%;
  126 + height: 100%;
  127 + }
  128 + .tags-li {
  129 + float: left;
  130 + margin: 3px 5px 2px 3px;
  131 + border-radius: 3px;
  132 + font-size: 12px;
  133 + overflow: hidden;
  134 + cursor: pointer;
  135 + height: 23px;
  136 + line-height: 23px;
  137 + border: 1px solid #e9eaec;
  138 + background: #fff;
  139 + padding: 0 5px 0 12px;
  140 + vertical-align: middle;
  141 + color: #666;
  142 + -webkit-transition: all .3s ease-in;
  143 + -moz-transition: all .3s ease-in;
  144 + transition: all .3s ease-in;
  145 + }
  146 + .tags-li:not(.active):hover {
  147 + background: #f8f8f8;
  148 + }
  149 + .tags-li.active {
  150 + color: #fff;
  151 + }
  152 + .tags-li-title {
  153 + float: left;
  154 + max-width: 80px;
  155 + overflow: hidden;
  156 + white-space: nowrap;
  157 + text-overflow: ellipsis;
  158 + margin-right: 5px;
  159 + color: #666;
  160 + }
  161 + .tags-li.active .tags-li-title {
  162 + color: #fff;
  163 + }
  164 + .tags-close-box {
  165 + position: absolute;
  166 + right: 0;
  167 + top: 0;
  168 + box-sizing: border-box;
  169 + padding-top: 1px;
  170 + text-align: center;
  171 + width: 110px;
  172 + height: 30px;
  173 + background: #fff;
  174 + box-shadow: -3px 0 15px 3px rgba(0, 0, 0, .1);
  175 + z-index: 10;
  176 + }
  177 +</style>
0 178 \ No newline at end of file
... ...
src/common/bus.js
... ... @@ -0,0 +1,6 @@
  1 +import Vue from 'vue';
  2 +
  3 +// 使用 Event Bus
  4 +const bus = new Vue();
  5 +
  6 +export default bus;
... ...
src/common/directives.js
... ... @@ -0,0 +1,80 @@
  1 +import Vue from 'vue';
  2 +
  3 +// v-dialogDrag: 弹窗拖拽属性
  4 +Vue.directive('dialogDrag', {
  5 + bind(el, binding, vnode, oldVnode) {
  6 + const dialogHeaderEl = el.querySelector('.el-dialog__header');
  7 + const dragDom = el.querySelector('.el-dialog');
  8 +
  9 + dialogHeaderEl.style.cssText += ';cursor:move;'
  10 + dragDom.style.cssText += ';top:0px;'
  11 +
  12 + // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
  13 + const sty = (() => {
  14 + if (window.document.currentStyle) {
  15 + return (dom, attr) => dom.currentStyle[attr];
  16 + } else {
  17 + return (dom, attr) => getComputedStyle(dom, false)[attr];
  18 + }
  19 + })()
  20 +
  21 + dialogHeaderEl.onmousedown = (e) => {
  22 + // 鼠标按下,计算当前元素距离可视区的距离
  23 + const disX = e.clientX - dialogHeaderEl.offsetLeft;
  24 + const disY = e.clientY - dialogHeaderEl.offsetTop;
  25 +
  26 + const screenWidth = document.body.clientWidth; // body当前宽度
  27 + const screenHeight = document.documentElement.clientHeight; // 可见区域高度(应为body高度,可某些环境下无法获取)
  28 +
  29 + const dragDomWidth = dragDom.offsetWidth; // 对话框宽度
  30 + const dragDomheight = dragDom.offsetHeight; // 对话框高度
  31 +
  32 + const minDragDomLeft = dragDom.offsetLeft;
  33 + const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
  34 +
  35 + const minDragDomTop = dragDom.offsetTop;
  36 + const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight;
  37 +
  38 +
  39 + // 获取到的值带px 正则匹配替换
  40 + let styL = sty(dragDom, 'left');
  41 + let styT = sty(dragDom, 'top');
  42 +
  43 + // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
  44 + if (styL.includes('%')) {
  45 + styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100);
  46 + styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100);
  47 + } else {
  48 + styL = +styL.replace(/\px/g, '');
  49 + styT = +styT.replace(/\px/g, '');
  50 + };
  51 +
  52 + document.onmousemove = function (e) {
  53 + // 通过事件委托,计算移动的距离
  54 + let left = e.clientX - disX;
  55 + let top = e.clientY - disY;
  56 +
  57 + // 边界处理
  58 + if (-(left) > minDragDomLeft) {
  59 + left = -(minDragDomLeft);
  60 + } else if (left > maxDragDomLeft) {
  61 + left = maxDragDomLeft;
  62 + }
  63 +
  64 + if (-(top) > minDragDomTop) {
  65 + top = -(minDragDomTop);
  66 + } else if (top > maxDragDomTop) {
  67 + top = maxDragDomTop;
  68 + }
  69 +
  70 + // 移动当前元素
  71 + dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
  72 + };
  73 +
  74 + document.onmouseup = function (e) {
  75 + document.onmousemove = null;
  76 + document.onmouseup = null;
  77 + };
  78 + }
  79 + }
  80 +})
0 81 \ No newline at end of file
... ...
src/common/i18n.js
... ... @@ -0,0 +1,30 @@
  1 +export const messages = {
  2 + 'zh': {
  3 + i18n: {
  4 + breadcrumb: '国际化产品',
  5 + tips: '通过切换语言按钮,来改变当前内容的语言。',
  6 + btn: '切换英文',
  7 + title1: '常用用法',
  8 + p1: '要是你把你的秘密告诉了风,那就别怪风把它带给树。',
  9 + p2: '没有什么比信念更能支撑我们度过艰难的时光了。',
  10 + p3: '只要能把自己的事做好,并让自己快乐,你就领先于大多数人了。',
  11 + title2: '组件插值',
  12 + info: 'Element组件需要国际化,请参考 {action}。',
  13 + value: '文档'
  14 + }
  15 + },
  16 + 'en': {
  17 + i18n: {
  18 + breadcrumb: 'International Products',
  19 + tips: 'Click on the button to change the current language. ',
  20 + btn: 'Switch Chinese',
  21 + title1: 'Common usage',
  22 + p1: "If you reveal your secrets to the wind you should not blame the wind for revealing them to the trees.",
  23 + p2: "Nothing can help us endure dark times better than our faith. ",
  24 + p3: "If you can do what you do best and be happy, you're further along in life than most people.",
  25 + title2: 'Component interpolation',
  26 + info: 'The default language of Element is Chinese. If you wish to use another language, please refer to the {action}.',
  27 + value: 'documentation'
  28 + }
  29 + }
  30 +}
0 31 \ No newline at end of file
... ...
src/layout/components/Navbar.vue
1 1 <template>
2 2 <div class="navbar">
3   - <hamburger :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
  3 + <hamburger
  4 + :is-active="sidebar.opened"
  5 + class="hamburger-container"
  6 + @toggleClick="toggleSideBar"
  7 + />
4 8  
5 9 <breadcrumb class="breadcrumb-container" />
6 10  
7 11 <div class="right-menu">
8   - 语言设置
9   - <el-dropdown class="avatar-container" trigger="click">
10   - <div class="avatar-wrapper">
11   - <img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar">
12   - <i class="el-icon-caret-bottom" />
13   - </div>
14   - <el-dropdown-menu slot="dropdown" class="user-dropdown">
15   - <router-link to="/">
16   - <el-dropdown-item>
17   - Home
18   - </el-dropdown-item>
19   - </router-link>
20   - <router-link to="/seting">
21   - <el-dropdown-item>
22   - 个人设置
23   - </el-dropdown-item>
24   - </router-link>
25   - <!-- <a target="_blank" href="https://github.com/PanJiaChen/vue-admin-template/">
  12 + <el-menu
  13 + :default-active="activeIndex"
  14 + class="el-menu-demo"
  15 + mode="horizontal"
  16 + @select="handleSelect"
  17 + >
  18 + <el-menu-item index="1">
  19 + <i class="el-icon-bell"></i>通知中心
  20 + <el-badge class="mark" :value="12" />
  21 + </el-menu-item>
  22 + <el-submenu index="2">
  23 + <template slot="title">
  24 + <i class="el-icon-custom"></i>个人设置
  25 + </template>
  26 + <el-menu-item index="2-1">选项1</el-menu-item>
  27 + <el-menu-item index="2-2">选项2</el-menu-item>
  28 + <el-menu-item index="2-3">选项3</el-menu-item>
  29 + </el-submenu>
  30 + <el-dropdown class="avatar-container" trigger="click">
  31 + <div class="avatar-wrapper">
  32 + <img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar" />
  33 + <i class="el-icon-caret-bottom" />
  34 + </div>
  35 + <el-dropdown-menu slot="dropdown" class="user-dropdown">
  36 + <router-link to="/">
  37 + <el-dropdown-item>Home</el-dropdown-item>
  38 + </router-link>
  39 + <router-link to="/seting">
  40 + <el-dropdown-item>个人设置</el-dropdown-item>
  41 + </router-link>
  42 + <!-- <a target="_blank" href="https://github.com/PanJiaChen/vue-admin-template/">
26 43 <el-dropdown-item>Github</el-dropdown-item>
27   - </a> -->
28   - <!-- <a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/">
  44 + </a>-->
  45 + <!-- <a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/">
29 46 <el-dropdown-item>Docs</el-dropdown-item>
30   - </a> -->
31   - <el-dropdown-item divided @click.native="logout">
32   - <span style="display:block;">退出系统</span>
33   - </el-dropdown-item>
34   - </el-dropdown-menu>
35   - </el-dropdown>
  47 + </a>-->
  48 + <el-dropdown-item divided @click.native="logout">
  49 + <span style="display:block;">退出系统</span>
  50 + </el-dropdown-item>
  51 + </el-dropdown-menu>
  52 + </el-dropdown>
  53 + <el-menu-item index="3" disabled>ddd</el-menu-item>
  54 + <el-menu-item index="4">
  55 + <a href="https://glass.xiuyetang.com" target="_blank">跳到外部链接</a>
  56 + </el-menu-item>
  57 + </el-menu>
36 58 </div>
37 59 </div>
38 60 </template>
39 61  
40 62 <script>
41   -import { mapGetters } from 'vuex'
42   -import Breadcrumb from '@/components/Breadcrumb'
43   -import Hamburger from '@/components/Hamburger'
  63 +import { mapGetters } from "vuex";
  64 +import Breadcrumb from "@/components/Breadcrumb";
  65 +import Hamburger from "@/components/Hamburger";
44 66  
45 67 export default {
46 68 components: {
... ... @@ -48,41 +70,42 @@ export default {
48 70 Hamburger
49 71 },
50 72 computed: {
51   - ...mapGetters([
52   - 'sidebar',
53   - 'avatar'
54   - ])
  73 + ...mapGetters(["sidebar", "avatar"])
55 74 },
56 75 methods: {
57 76 toggleSideBar() {
58   - this.$store.dispatch('app/toggleSideBar')
  77 + this.$store.dispatch("app/toggleSideBar");
59 78 },
60 79 async logout() {
61   - await this.$store.dispatch('user/logout')
62   - this.$router.push(`/login?redirect=${this.$route.fullPath}`)
  80 + await this.$store.dispatch("user/logout");
  81 + this.$router.push(`/login?redirect=${this.$route.fullPath}`);
63 82 }
64 83 }
65   -}
  84 +};
66 85 </script>
67 86  
68 87 <style lang="scss" scoped>
  88 +.item {
  89 + margin-top: 10px;
  90 + margin-right: 20px;
  91 +}
69 92 .navbar {
70 93 height: 50px;
71 94 overflow: hidden;
72 95 position: relative;
73 96 background: #fff;
74   - box-shadow: 0 1px 4px rgba(0,21,41,.08);
  97 + box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
75 98  
76 99 .hamburger-container {
77 100 line-height: 46px;
78 101 height: 100%;
79 102 float: left;
80 103 cursor: pointer;
81   - transition: background .3s;
82   - -webkit-tap-highlight-color:transparent;
  104 + transition: background 0.3s;
  105 + -webkit-tap-highlight-color: transparent;
83 106  
84 107 &:hover {
85   - background: rgba(0, 0, 0, .025)
  108 + background: rgba(0, 0, 0, 0.025);
86 109 }
87 110 }
88 111  
... ... @@ -109,10 +132,10 @@ export default {
109 132  
110 133 &.hover-effect {
111 134 cursor: pointer;
112   - transition: background .3s;
  135 + transition: background 0.3s;
113 136  
114 137 &:hover {
115   - background: rgba(0, 0, 0, .025)
  138 + background: rgba(0, 0, 0, 0.025);
116 139 }
117 140 }
118 141 }
... ...
src/layout/components/index.js
  1 +// export { default as Navbar } from '../../common/Header'
1 2 export { default as Navbar } from './Navbar'
2 3 export { default as Sidebar } from './Sidebar'
3 4 export { default as AppMain } from './AppMain'
... ...
... ... @@ -4,7 +4,7 @@ import &#39;normalize.css/normalize.css&#39; // A modern alternative to CSS resets
4 4  
5 5 import ElementUI from 'element-ui'
6 6 import 'element-ui/lib/theme-chalk/index.css'
7   -import locale from 'element-ui/lib/locale/lang/en' // lang i18n
  7 +// import locale from 'element-ui/lib/locale/lang/en' // lang i18n
8 8 // import local_zh from 'element-ui/lib/locale/lang/zh-CN' // 在node_module里面
9 9  
10 10 import '@/styles/index.scss' // global css
... ... @@ -29,11 +29,11 @@ if (process.env.NODE_ENV === &#39;production&#39;) {
29 29 mockXHR()
30 30 }
31 31  
  32 +Vue.use(ElementUI, { size: 'small', zIndex: 3000 })
32 33 // set ElementUI lang to EN
33   -Vue.use(ElementUI, { locale })
  34 +// Vue.use(ElementUI, { locale })
34 35 // 如果想要中文版 element-ui,按如下方式声明
35 36 // Vue.use(ElementUI, {local_zh})
36   -
37 37 Vue.config.productionTip = false
38 38  
39 39 new Vue({
... ...
src/router/index.js
... ... @@ -30,8 +30,7 @@ import Layout from &#39;@/layout&#39;
30 30 * a base page that does not have permission requirements
31 31 * all roles can be accessed
32 32 */
33   -export const constantRoutes = [
34   - {
  33 +export const constantRoutes = [{
35 34 path: '/login',
36 35 component: () => import('@/views/login/index'),
37 36 hidden: true
... ... @@ -51,7 +50,10 @@ export const constantRoutes = [
51 50 path: 'dashboard',
52 51 name: 'Dashboard',
53 52 component: () => import('@/views/dashboard/index'),
54   - meta: { title: '中控台', icon: 'dashboard' }
  53 + meta: {
  54 + title: '中控台',
  55 + icon: 'dashboard'
  56 + }
55 57 }]
56 58 },
57 59 {
... ... @@ -59,19 +61,27 @@ export const constantRoutes = [
59 61 component: Layout,
60 62 redirect: '/user/list',
61 63 name: 'user',
62   - meta: { title: '用户管理', icon: 'example' },
63   - children: [
64   - {
  64 + meta: {
  65 + title: '用户管理',
  66 + icon: 'example'
  67 + },
  68 + children: [{
65 69 path: 'user',
66 70 name: 'User',
67 71 component: () => import('@/views/table/index'),
68   - meta: { title: '用户列表', icon: 'table' }
  72 + meta: {
  73 + title: '用户列表',
  74 + icon: 'table'
  75 + }
69 76 },
70 77 {
71 78 path: 'tree',
72 79 name: 'Table',
73 80 component: () => import('@/views/tree/index'),
74   - meta: { title: 'Tree', icon: 'tree' }
  81 + meta: {
  82 + title: 'Tree',
  83 + icon: 'tree'
  84 + }
75 85 }
76 86 ]
77 87 },
... ... @@ -80,110 +90,229 @@ export const constantRoutes = [
80 90 component: Layout,
81 91 redirect: '/example/table',
82 92 name: 'Example',
83   - meta: { title: 'E1111xample', icon: 'example' },
84   - children: [
85   - {
  93 + meta: {
  94 + title: '商家管理',
  95 + icon: 'example'
  96 + },
  97 + children: [{
86 98 path: 'table',
87 99 name: 'Table',
88 100 component: () => import('@/views/table/index'),
89   - meta: { title: 'Table', icon: 'table' }
  101 + meta: {
  102 + title: 'Table',
  103 + icon: 'table'
  104 + }
90 105 },
91 106 {
92 107 path: 'tree',
93 108 name: 'Tree',
94 109 component: () => import('@/views/tree/index'),
95   - meta: { title: 'Tree', icon: 'tree' }
  110 + meta: {
  111 + title: 'Tree',
  112 + icon: 'tree'
  113 + }
96 114 }
97 115 ]
98 116 },
99   -
100 117 {
101   - path: '/form',
  118 + path: '/example',
102 119 component: Layout,
103   - children: [
  120 + redirect: '/example/table',
  121 + name: 'Example',
  122 + meta: {
  123 + title: '产品管理',
  124 + icon: 'example'
  125 + },
  126 + children: [{
  127 + path: 'table',
  128 + name: 'Table',
  129 + component: () => import('@/views/table/index'),
  130 + meta: {
  131 + title: 'Table',
  132 + icon: 'table'
  133 + }
  134 + },
104 135 {
105   - path: 'index',
106   - name: 'Form',
107   - component: () => import('@/views/form/index'),
108   - meta: { title: 'Form', icon: 'form' }
  136 + path: 'tree',
  137 + name: 'Tree',
  138 + component: () => import('@/views/tree/index'),
  139 + meta: {
  140 + title: 'Tree',
  141 + icon: 'tree'
  142 + }
109 143 }
110 144 ]
111   - }
112   -]
113   -
114   -/**
115   - * asyncRoutes
116   - * the routes that need to be dynamically loaded based on user roles
117   - */
118   -export const asyncRoutes = [
  145 + },
119 146 {
120   - path: '/nested',
  147 + path: '/example',
121 148 component: Layout,
122   - redirect: '/nested/menu1',
123   - name: 'Nested',
  149 + redirect: '/example/table',
  150 + name: 'Example',
124 151 meta: {
125   - title: 'Nested',
126   - icon: 'nested'
  152 + title: '元管理',
  153 + icon: 'example'
127 154 },
128   - children: [
129   - {
130   - path: 'menu1',
131   - component: () => import('@/views/nested/menu1/index'), // Parent router-view
132   - name: 'Menu1',
133   - meta: { title: 'Menu1' },
134   - children: [
135   - {
136   - path: 'menu1-1',
137   - component: () => import('@/views/nested/menu1/menu1-1'),
138   - name: 'Menu1-1',
139   - meta: { title: 'Menu1-1' }
140   - },
141   - {
142   - path: 'menu1-2',
143   - component: () => import('@/views/nested/menu1/menu1-2'),
144   - name: 'Menu1-2',
145   - meta: { title: 'Menu1-2' },
146   - children: [
147   - {
148   - path: 'menu1-2-1',
149   - component: () => import('@/views/nested/menu1/menu1-2/menu1-2-1'),
150   - name: 'Menu1-2-1',
151   - meta: { title: 'Menu1-2-1' }
152   - },
153   - {
154   - path: 'menu1-2-2',
155   - component: () => import('@/views/nested/menu1/menu1-2/menu1-2-2'),
156   - name: 'Menu1-2-2',
157   - meta: { title: 'Menu1-2-2' }
158   - }
159   - ]
160   - },
161   - {
162   - path: 'menu1-3',
163   - component: () => import('@/views/nested/menu1/menu1-3'),
164   - name: 'Menu1-3',
165   - meta: { title: 'Menu1-3' }
166   - }
167   - ]
  155 + children: [{
  156 + path: 'table',
  157 + name: 'Table',
  158 + component: () => import('@/views/table/index'),
  159 + meta: {
  160 + title: 'Table',
  161 + icon: 'table'
  162 + }
168 163 },
169 164 {
170   - path: 'menu2',
171   - component: () => import('@/views/nested/menu2/index'),
172   - meta: { title: 'menu2' }
  165 + path: 'tree',
  166 + name: 'Tree',
  167 + component: () => import('@/views/tree/index'),
  168 + meta: {
  169 + title: 'Tree',
  170 + icon: 'tree'
  171 + }
173 172 }
174 173 ]
175 174 },
176   -
177 175 {
178   - path: 'external-link',
  176 + path: '/example',
  177 + component: Layout,
  178 + redirect: '/example/table',
  179 + name: 'Example',
  180 + meta: {
  181 + title: '交易管理',
  182 + icon: 'example'
  183 + },
  184 + children: [{
  185 + path: 'table',
  186 + name: 'Table',
  187 + component: () => import('@/views/table/index'),
  188 + meta: {
  189 + title: 'Table',
  190 + icon: 'table'
  191 + }
  192 + },
  193 + {
  194 + path: 'tree',
  195 + name: 'Tree',
  196 + component: () => import('@/views/tree/index'),
  197 + meta: {
  198 + title: 'Tree',
  199 + icon: 'tree'
  200 + }
  201 + }
  202 + ]
  203 + }, {
  204 + path: '/example',
179 205 component: Layout,
180   - children: [
  206 + redirect: '/example/table',
  207 + name: 'Example',
  208 + meta: {
  209 + title: '推荐系统',
  210 + icon: 'example'
  211 + },
  212 + children: [{
  213 + path: 'table',
  214 + name: 'Table',
  215 + component: () => import('@/views/table/index'),
  216 + meta: {
  217 + title: 'Table',
  218 + icon: 'table'
  219 + }
  220 + },
  221 + {
  222 + path: 'tree',
  223 + name: 'Tree',
  224 + component: () => import('@/views/tree/index'),
  225 + meta: {
  226 + title: 'Tree',
  227 + icon: 'tree'
  228 + }
  229 + }
  230 + ]
  231 + }, {
  232 + path: '/system',
  233 + component: Layout,
  234 + redirect: '/system/table',
  235 + name: 'System',
  236 + meta: {
  237 + title: '系统设置',
  238 + icon: 'example'
  239 + },
  240 + children: [{
  241 + path: 'table',
  242 + name: 'Table',
  243 + component: () => import('@/views/table/index'),
  244 + meta: {
  245 + title: '行业设置',
  246 + icon: 'table'
  247 + }
  248 + },
  249 + {
  250 + path: 'tree',
  251 + name: 'Tree',
  252 + component: () => import('@/views/tree/index'),
  253 + meta: {
  254 + title: '语言设置',
  255 + icon: 'tree'
  256 + }
  257 + },
  258 + {
  259 + path: 'tree',
  260 + name: 'Tree',
  261 + component: () => import('@/views/tree/index'),
  262 + meta: {
  263 + title: '货币设置',
  264 + icon: 'tree'
  265 + }
  266 + },
  267 + {
  268 + path: 'tree',
  269 + name: 'Tree',
  270 + component: () => import('@/views/tree/index'),
  271 + meta: {
  272 + title: '站点类型设置',
  273 + icon: 'tree'
  274 + }
  275 + },
  276 + {
  277 + path: 'tree',
  278 + name: 'Tree',
  279 + component: () => import('@/views/tree/index'),
  280 + meta: {
  281 + title: '模版设置',
  282 + icon: 'tree'
  283 + }
  284 + },
181 285 {
182   - path: 'https://panjiachen.github.io/vue-element-admin-site/#/',
183   - meta: { title: 'External Link', icon: 'link' }
  286 + path: 'tree',
  287 + name: 'Tree',
  288 + component: () => import('@/views/tree/index'),
  289 + meta: {
  290 + title: '权限设置',
  291 + icon: 'tree'
  292 + }
184 293 }
185 294 ]
186 295 },
  296 + {
  297 + path: '/form',
  298 + component: Layout,
  299 + children: [{
  300 + path: 'index',
  301 + name: 'Form',
  302 + component: () => import('@/views/form/index'),
  303 + meta: {
  304 + title: 'Form',
  305 + icon: 'form'
  306 + }
  307 + }]
  308 + }
  309 +]
  310 +
  311 +/**
  312 + * asyncRoutes
  313 + * the routes that need to be dynamically loaded based on user roles
  314 + */
  315 +export const asyncRoutes = [
187 316 // 404 page must be placed at the end !!!
188 317 {
189 318 path: '*',
... ... @@ -193,7 +322,9 @@ export const asyncRoutes = [
193 322  
194 323 const createRouter = () => new Router({
195 324 // mode: 'history', // require service support
196   - scrollBehavior: () => ({ y: 0 }),
  325 + scrollBehavior: () => ({
  326 + y: 0
  327 + }),
197 328 routes: constantRoutes
198 329 })
199 330  
... ...
src/views/403.vue
... ... @@ -0,0 +1,59 @@
  1 +<template>
  2 + <div class="error-page">
  3 + <div class="error-code">
  4 + 4
  5 + <span>0</span>3
  6 + </div>
  7 + <div class="error-desc">啊哦~ 你没有权限访问该页面哦</div>
  8 + <div class="error-handle">
  9 + <router-link to="/">
  10 + <el-button type="primary" size="large">返回首页</el-button>
  11 + </router-link>
  12 + <el-button class="error-btn" type="primary" size="large" @click="goBack">返回上一页</el-button>
  13 + </div>
  14 + </div>
  15 +</template>
  16 +
  17 +<script>
  18 +export default {
  19 + methods: {
  20 + goBack() {
  21 + this.$router.go(-1);
  22 + }
  23 + }
  24 +};
  25 +</script>
  26 +
  27 +
  28 +<style scoped>
  29 +.error-page {
  30 + display: flex;
  31 + justify-content: center;
  32 + align-items: center;
  33 + flex-direction: column;
  34 + width: 100%;
  35 + height: 100%;
  36 + background: #f3f3f3;
  37 + box-sizing: border-box;
  38 +}
  39 +.error-code {
  40 + line-height: 1;
  41 + font-size: 250px;
  42 + font-weight: bolder;
  43 + color: #f02d2d;
  44 +}
  45 +.error-code span {
  46 + color: #00a854;
  47 +}
  48 +.error-desc {
  49 + font-size: 30px;
  50 + color: #777;
  51 +}
  52 +.error-handle {
  53 + margin-top: 30px;
  54 + padding-bottom: 200px;
  55 +}
  56 +.error-btn {
  57 + margin-left: 100px;
  58 +}
  59 +</style>
0 60 \ No newline at end of file
... ...
src/views/404.vue
... ... @@ -2,39 +2,45 @@
2 2 <div class="wscn-http404-container">
3 3 <div class="wscn-http404">
4 4 <div class="pic-404">
5   - <img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404">
6   - <img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404">
7   - <img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404">
8   - <img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404">
  5 + <img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404" />
  6 + <img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404" />
  7 + <img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404" />
  8 + <img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404" />
9 9 </div>
10 10 <div class="bullshit">
11 11 <div class="bullshit__oops">OOPS!</div>
12   - <div class="bullshit__info">All rights reserved
13   - <a style="color:#20a0ff" href="https://wallstreetcn.com" target="_blank">wallstreetcn</a>
  12 + <div class="bullshit__info">
  13 + All rights reserved
  14 + <a
  15 + style="color:#20a0ff"
  16 + href="https://wallstreetcn.com"
  17 + target="_blank"
  18 + >wallstreetcn</a>
14 19 </div>
15 20 <div class="bullshit__headline">{{ message }}</div>
16   - <div class="bullshit__info">Please check that the URL you entered is correct, or click the button below to return to the homepage.</div>
17   - <a href="" class="bullshit__return-home">Back to home</a>
  21 + <div
  22 + class="bullshit__info"
  23 + >Please check that the URL you entered is correct, or click the button below to return to the homepage.</div>
  24 + <a href class="bullshit__return-home">Back to home</a>
18 25 </div>
19 26 </div>
20 27 </div>
21 28 </template>
22 29  
23 30 <script>
24   -
25 31 export default {
26   - name: 'Page404',
  32 + name: "Page404",
27 33 computed: {
28 34 message() {
29   - return 'The webmaster said that you can not enter this page...'
  35 + return "The webmaster said that you can not enter this page...";
30 36 }
31 37 }
32   -}
  38 +};
33 39 </script>
34 40  
35 41 <style lang="scss" scoped>
36   -.wscn-http404-container{
37   - transform: translate(-50%,-50%);
  42 +.wscn-http404-container {
  43 + transform: translate(-50%, -50%);
38 44 position: absolute;
39 45 top: 40%;
40 46 left: 50%;
... ...
src/views/502.vue
... ... @@ -0,0 +1,57 @@
  1 +<template>
  2 + <div class="error-page">
  3 + <div class="error-code">
  4 + 5
  5 + <span>0</span>2
  6 + </div>
  7 + <div class="error-desc">啊哦~ 系统出了故障!</div>
  8 + <div class="error-handle">
  9 + <router-link to="/">
  10 + <el-button type="primary" size="large">返回首页</el-button>
  11 + </router-link>
  12 + <el-button class="error-btn" type="primary" size="large" @click="goBack">返回上一页</el-button>
  13 + </div>
  14 + </div>
  15 +</template>
  16 +
  17 +<script>
  18 +export default {
  19 + methods: {
  20 + goBack() {
  21 + this.$router.go(-1);
  22 + }
  23 + }
  24 +};
  25 +</script>
  26 +<style scoped>
  27 +.error-page {
  28 + display: flex;
  29 + justify-content: center;
  30 + align-items: center;
  31 + flex-direction: column;
  32 + width: 100%;
  33 + height: 100%;
  34 + background: #f3f3f3;
  35 + box-sizing: border-box;
  36 +}
  37 +.error-code {
  38 + line-height: 1;
  39 + font-size: 250px;
  40 + font-weight: bolder;
  41 + color: #f02d2d;
  42 +}
  43 +.error-code span {
  44 + color: #00a854;
  45 +}
  46 +.error-desc {
  47 + font-size: 30px;
  48 + color: #777;
  49 +}
  50 +.error-handle {
  51 + margin-top: 30px;
  52 + padding-bottom: 200px;
  53 +}
  54 +.error-btn {
  55 + margin-left: 100px;
  56 +}
  57 +</style>
0 58 \ No newline at end of file
... ...
src/views/dashboard/index.vue
1 1 <template>
2   - <div class="dashboard-container">
3   - <div class="dashboard-text">用户名: {{ name }}</div>
4   - <div class="dashboard-text">角色: <span v-for="role in roles" :key="role">{{ role }}</span></div>
  2 + <div>
  3 + <el-row :gutter="20">
  4 + <el-col :span="8">
  5 + <el-card shadow="hover" class="mgb20" style="height:252px;">
  6 + <div class="user-info">
  7 + <img src="../../assets/img/img.jpg" class="user-avator" alt />
  8 + <div class="user-info-cont">
  9 + <div class="user-info-name">{{name}}</div>
  10 + <div>{{role}}</div>
  11 + </div>
  12 + </div>
  13 + <div class="user-info-list">
  14 + 上次登录时间:
  15 + <span>2019-11-01</span>
  16 + </div>
  17 + <div class="user-info-list">
  18 + 上次登录地点:
  19 + <span>东莞</span>
  20 + </div>
  21 + </el-card>
  22 + <el-card shadow="hover" style="height:252px;">
  23 + <div slot="header" class="clearfix">
  24 + <span>语言详情</span>
  25 + </div>Vue
  26 + <el-progress :percentage="71.3" color="#42b983"></el-progress>JavaScript
  27 + <el-progress :percentage="24.1" color="#f1e05a"></el-progress>CSS
  28 + <el-progress :percentage="13.7"></el-progress>HTML
  29 + <el-progress :percentage="5.9" color="#f56c6c"></el-progress>
  30 + </el-card>
  31 + </el-col>
  32 + <el-col :span="16">
  33 + <el-row :gutter="20" class="mgb20">
  34 + <el-col :span="8">
  35 + <el-card shadow="hover" :body-style="{padding: '0px'}">
  36 + <div class="grid-content grid-con-1">
  37 + <i class="el-icon-lx-people grid-con-icon"></i>
  38 + <div class="grid-cont-right">
  39 + <div class="grid-num">1234</div>
  40 + <div>用户访问量</div>
  41 + </div>
  42 + </div>
  43 + </el-card>
  44 + </el-col>
  45 + <el-col :span="8">
  46 + <el-card shadow="hover" :body-style="{padding: '0px'}">
  47 + <div class="grid-content grid-con-2">
  48 + <i class="el-icon-lx-notice grid-con-icon"></i>
  49 + <div class="grid-cont-right">
  50 + <div class="grid-num">321</div>
  51 + <div>系统消息</div>
  52 + </div>
  53 + </div>
  54 + </el-card>
  55 + </el-col>
  56 + <el-col :span="8">
  57 + <el-card shadow="hover" :body-style="{padding: '0px'}">
  58 + <div class="grid-content grid-con-3">
  59 + <i class="el-icon-lx-goods grid-con-icon"></i>
  60 + <div class="grid-cont-right">
  61 + <div class="grid-num">5000</div>
  62 + <div>数量</div>
  63 + </div>
  64 + </div>
  65 + </el-card>
  66 + </el-col>
  67 + </el-row>
  68 + <el-card shadow="hover" style="height:403px;">
  69 + <div slot="header" class="clearfix">
  70 + <span>待办事项</span>
  71 + <el-button style="float: right; padding: 3px 0" type="text" @click="addAction">添加</el-button>
  72 + </div>
  73 + <el-table :show-header="false" :data="todoList" style="width:100%;">
  74 + <el-table-column width="40">
  75 + <template slot-scope="scope">
  76 + <el-checkbox v-model="scope.row.status"></el-checkbox>
  77 + </template>
  78 + </el-table-column>
  79 + <el-table-column>
  80 + <template slot-scope="scope">
  81 + <div
  82 + class="todo-item"
  83 + :class="{'todo-item-del': scope.row.status}"
  84 + >{{scope.row.title}}</div>
  85 + </template>
  86 + </el-table-column>
  87 + <el-table-column width="60">
  88 + <template>
  89 + <i class="el-icon-edit" @click="modiAction"></i>
  90 + <i class="el-icon-delete" @click="delAction"></i>
  91 + </template>
  92 + </el-table-column>
  93 + </el-table>
  94 + </el-card>
  95 + </el-col>
  96 + </el-row>
  97 + <el-row :gutter="20">
  98 + <el-col :span="12">
  99 + <el-card shadow="hover">
  100 + <schart ref="bar" class="schart" canvasId="bar" :options="options"></schart>
  101 + </el-card>
  102 + </el-col>
  103 + <el-col :span="12">
  104 + <el-card shadow="hover">
  105 + <schart ref="line" class="schart" canvasId="line" :options="options2"></schart>
  106 + </el-card>
  107 + </el-col>
  108 + </el-row>
5 109 </div>
6 110 </template>
7 111  
8 112 <script>
9   -import { mapGetters } from 'vuex'
  113 +import { mapGetters } from "vuex";
  114 +import Vue from "vue";
  115 +import {
  116 + Pagination,
  117 + Dialog,
  118 + Autocomplete,
  119 + Dropdown,
  120 + DropdownMenu,
  121 + DropdownItem,
  122 + Menu,
  123 + Submenu,
  124 + MenuItem,
  125 + MenuItemGroup,
  126 + Input,
  127 + InputNumber,
  128 + Radio,
  129 + RadioGroup,
  130 + RadioButton,
  131 + Checkbox,
  132 + CheckboxButton,
  133 + CheckboxGroup,
  134 + Switch,
  135 + Select,
  136 + Option,
  137 + OptionGroup,
  138 + Button,
  139 + ButtonGroup,
  140 + Table,
  141 + TableColumn,
  142 + DatePicker,
  143 + TimeSelect,
  144 + TimePicker,
  145 + Popover,
  146 + Tooltip,
  147 + Breadcrumb,
  148 + BreadcrumbItem,
  149 + Form,
  150 + FormItem,
  151 + Tabs,
  152 + TabPane,
  153 + Tag,
  154 + Tree,
  155 + Alert,
  156 + Slider,
  157 + Icon,
  158 + Row,
  159 + Col,
  160 + Upload,
  161 + Progress,
  162 + Spinner,
  163 + Badge,
  164 + Card,
  165 + Rate,
  166 + Steps,
  167 + Step,
  168 + Carousel,
  169 + CarouselItem,
  170 + Collapse,
  171 + CollapseItem,
  172 + Cascader,
  173 + ColorPicker,
  174 + Transfer,
  175 + Container,
  176 + Header,
  177 + Aside,
  178 + Main,
  179 + Footer,
  180 + Timeline,
  181 + TimelineItem,
  182 + Link,
  183 + Divider,
  184 + Image,
  185 + Calendar,
  186 + Backtop,
  187 + PageHeader,
  188 + CascaderPanel,
  189 + Loading,
  190 + MessageBox,
  191 + Message,
  192 + Notification
  193 +} from "element-ui";
10 194 // import ElementUI from 'element-ui'
  195 +Vue.prototype.$ELEMENT = { size: "small", zIndex: 3000 };
  196 +Vue.use(Pagination);
  197 +Vue.use(Dialog);
  198 +Vue.use(Autocomplete);
  199 +Vue.use(Dropdown);
  200 +Vue.use(DropdownMenu);
  201 +Vue.use(DropdownItem);
  202 +Vue.use(Menu);
  203 +Vue.use(Submenu);
  204 +Vue.use(MenuItem);
  205 +Vue.use(MenuItemGroup);
  206 +Vue.use(Input);
  207 +Vue.use(InputNumber);
  208 +Vue.use(Radio);
  209 +Vue.use(RadioGroup);
  210 +Vue.use(RadioButton);
  211 +Vue.use(Checkbox);
  212 +Vue.use(CheckboxButton);
  213 +Vue.use(CheckboxGroup);
  214 +Vue.use(Switch);
  215 +Vue.use(Select);
  216 +Vue.use(Option);
  217 +Vue.use(OptionGroup);
  218 +Vue.use(Button);
  219 +Vue.use(ButtonGroup);
  220 +Vue.use(Table);
  221 +Vue.use(TableColumn);
  222 +Vue.use(DatePicker);
  223 +Vue.use(TimeSelect);
  224 +Vue.use(TimePicker);
  225 +Vue.use(Popover);
  226 +Vue.use(Tooltip);
  227 +Vue.use(Breadcrumb);
  228 +Vue.use(BreadcrumbItem);
  229 +Vue.use(Form);
  230 +Vue.use(FormItem);
  231 +Vue.use(Tabs);
  232 +Vue.use(TabPane);
  233 +Vue.use(Tag);
  234 +Vue.use(Tree);
  235 +Vue.use(Alert);
  236 +Vue.use(Slider);
  237 +Vue.use(Icon);
  238 +Vue.use(Row);
  239 +Vue.use(Col);
  240 +Vue.use(Upload);
  241 +Vue.use(Progress);
  242 +Vue.use(Spinner);
  243 +Vue.use(Badge);
  244 +Vue.use(Card);
  245 +Vue.use(Rate);
  246 +Vue.use(Steps);
  247 +Vue.use(Step);
  248 +Vue.use(Carousel);
  249 +Vue.use(CarouselItem);
  250 +Vue.use(Collapse);
  251 +Vue.use(CollapseItem);
  252 +Vue.use(Cascader);
  253 +Vue.use(ColorPicker);
  254 +Vue.use(Transfer);
  255 +Vue.use(Container);
  256 +Vue.use(Header);
  257 +Vue.use(Aside);
  258 +Vue.use(Main);
  259 +Vue.use(Footer);
  260 +Vue.use(Timeline);
  261 +Vue.use(TimelineItem);
  262 +Vue.use(Link);
  263 +Vue.use(Divider);
  264 +Vue.use(Image);
  265 +Vue.use(Calendar);
  266 +Vue.use(Backtop);
  267 +Vue.use(PageHeader);
  268 +Vue.use(CascaderPanel);
  269 +Vue.use(Loading.directive);
  270 +
  271 +import Schart from "vue-schart";
  272 +import bus from "../../common/bus";
  273 +
11 274 // 按需引入 引入 ECharts 主模块
12 275 // var echarts = require('echarts/lib/echarts')
13 276 // 引入柱状图
... ... @@ -19,24 +282,239 @@ import { mapGetters } from &#39;vuex&#39;
19 282 // var echarts = require('echarts')
20 283  
21 284 export default {
22   - name: 'Dashboard',
  285 + name: "Dashboard",
  286 + data() {
  287 + return {
  288 + name: localStorage.getItem("ms_username"),
  289 + todoList: [
  290 + {
  291 + title: "今天要修复100个bug",
  292 + status: true
  293 + },
  294 + {
  295 + title: "今天要写100行代码加几个bug吧",
  296 + status: true
  297 + }
  298 + ],
  299 + data: [
  300 + {
  301 + name: "2018/09/04",
  302 + value: 1083
  303 + },
  304 + {
  305 + name: "2018/09/10",
  306 + value: 1065
  307 + }
  308 + ],
  309 + options: {
  310 + type: "bar",
  311 + title: {
  312 + text: "最近一周各品类销售图"
  313 + },
  314 + xRorate: 25,
  315 + labels: ["周一", "周二", "周三", "周四", "周五"],
  316 + datasets: [
  317 + {
  318 + label: "百货",
  319 + data: [164, 178, 190, 135, 160]
  320 + },
  321 + {
  322 + label: "食品",
  323 + data: [144, 198, 150, 235, 120]
  324 + }
  325 + ]
  326 + },
  327 + options2: {
  328 + type: "line",
  329 + title: {
  330 + text: "最近几个月各品类销售趋势图"
  331 + },
  332 + labels: ["6月", "7月", "8月", "9月", "10月"],
  333 + datasets: [
  334 + {
  335 + label: "百货",
  336 + data: [164, 178, 150, 135, 160]
  337 + },
  338 + {
  339 + label: "食品",
  340 + data: [74, 118, 200, 235, 90]
  341 + }
  342 + ]
  343 + }
  344 + };
  345 + },
  346 + components: {
  347 + Schart
  348 + },
23 349 computed: {
24   - ...mapGetters([
25   - 'name',
26   - 'roles'
27   - ])
  350 + // ...mapGetters(["name", "roles"])
  351 + role() {
  352 + return this.name === "admin" ? "超级管理员" : "普通用户";
  353 + }
  354 + },
  355 + methods: {
  356 + addAction(){
  357 + this.$prompt("请输入内容", "提示", {
  358 + confirmButtonText: "确定",
  359 + cancelButtonText: "取消",
  360 + inputErrorMessage: "内容不能为空"
  361 + })
  362 + .then(({ value }) => {
  363 + this.$message({
  364 + type: "success",
  365 + message: "你的邮箱是: " + value
  366 + });
  367 + })
  368 + .catch(() => {
  369 + this.$message({
  370 + type: "info",
  371 + message: "取消输入"
  372 + });
  373 + });
  374 + },
  375 + modiAction() {
  376 + // this.$prompt("请输入邮箱", "提示", {
  377 + // confirmButtonText: "确定",
  378 + // cancelButtonText: "取消",
  379 + // inputPattern: /[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/,
  380 + // inputErrorMessage: "邮箱格式不正确"
  381 + // })
  382 + this.$prompt("请输入内容", "提示", {
  383 + confirmButtonText: "确定",
  384 + cancelButtonText: "取消",
  385 + inputErrorMessage: "内容不能为空"
  386 + })
  387 + .then(({ value }) => {
  388 + this.$message({
  389 + type: "success",
  390 + message: "你的邮箱是: " + value
  391 + });
  392 + })
  393 + .catch(() => {
  394 + this.$message({
  395 + type: "info",
  396 + message: "取消输入"
  397 + });
  398 + });
  399 + },
  400 + delAction() {
  401 + this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
  402 + confirmButtonText: "确定",
  403 + cancelButtonText: "取消",
  404 + type: "warning"
  405 + })
  406 + .then(() => {
  407 + this.$message({
  408 + type: "success",
  409 + message: "删除成功!"
  410 + });
  411 + })
  412 + .catch(() => {
  413 + this.$message({
  414 + type: "info",
  415 + message: "已取消删除"
  416 + });
  417 + });
  418 + },
  419 + changeDate() {
  420 + const now = new Date().getTime();
  421 + this.data.forEach((item, index) => {
  422 + const date = new Date(now - (6 - index) * 86400000);
  423 + item.name = `${date.getFullYear()}/${date.getMonth() +
  424 + 1}/${date.getDate()}`;
  425 + });
  426 + }
28 427 }
29   -}
  428 +};
30 429 </script>
31 430  
32   -<style lang="scss" scoped>
33   -.dashboard {
34   - &-container {
35   - margin: 30px;
36   - }
37   - &-text {
38   - font-size: 30px;
39   - line-height: 46px;
40   - }
  431 +<style scoped>
  432 +.el-row {
  433 + margin-bottom: 20px;
  434 +}
  435 +.grid-content {
  436 + display: flex;
  437 + align-items: center;
  438 + height: 100px;
  439 +}
  440 +.grid-cont-right {
  441 + flex: 1;
  442 + text-align: center;
  443 + font-size: 14px;
  444 + color: #999;
  445 +}
  446 +.grid-num {
  447 + font-size: 30px;
  448 + font-weight: bold;
  449 +}
  450 +.grid-con-icon {
  451 + font-size: 50px;
  452 + width: 100px;
  453 + height: 100px;
  454 + text-align: center;
  455 + line-height: 100px;
  456 + color: #fff;
  457 +}
  458 +.grid-con-1 .grid-con-icon {
  459 + background: rgb(45, 140, 240);
  460 +}
  461 +.grid-con-1 .grid-num {
  462 + color: rgb(45, 140, 240);
  463 +}
  464 +.grid-con-2 .grid-con-icon {
  465 + background: rgb(100, 213, 114);
  466 +}
  467 +.grid-con-2 .grid-num {
  468 + color: rgb(45, 140, 240);
  469 +}
  470 +.grid-con-3 .grid-con-icon {
  471 + background: rgb(242, 94, 67);
  472 +}
  473 +.grid-con-3 .grid-num {
  474 + color: rgb(242, 94, 67);
  475 +}
  476 +.user-info {
  477 + display: flex;
  478 + align-items: center;
  479 + padding-bottom: 20px;
  480 + border-bottom: 2px solid #ccc;
  481 + margin-bottom: 20px;
  482 +}
  483 +.user-avator {
  484 + width: 120px;
  485 + height: 120px;
  486 + border-radius: 50%;
  487 +}
  488 +.user-info-cont {
  489 + padding-left: 50px;
  490 + flex: 1;
  491 + font-size: 14px;
  492 + color: #999;
  493 +}
  494 +.user-info-cont div:first-child {
  495 + font-size: 30px;
  496 + color: #222;
  497 +}
  498 +.user-info-list {
  499 + font-size: 14px;
  500 + color: #999;
  501 + line-height: 25px;
  502 +}
  503 +.user-info-list span {
  504 + margin-left: 70px;
  505 +}
  506 +.mgb20 {
  507 + margin-bottom: 20px;
  508 +}
  509 +.todo-item {
  510 + font-size: 14px;
  511 +}
  512 +.todo-item-del {
  513 + text-decoration: line-through;
  514 + color: #999;
  515 +}
  516 +.schart {
  517 + width: 100%;
  518 + height: 300px;
41 519 }
42 520 </style>
... ...
src/views/form/index.vue
... ... @@ -12,11 +12,21 @@
12 12 </el-form-item>
13 13 <el-form-item label="Activity time">
14 14 <el-col :span="11">
15   - <el-date-picker v-model="form.date1" type="date" placeholder="Pick a date" style="width: 100%;" />
  15 + <el-date-picker
  16 + v-model="form.date1"
  17 + type="date"
  18 + placeholder="Pick a date"
  19 + style="width: 100%;"
  20 + />
16 21 </el-col>
17 22 <el-col :span="2" class="line">-</el-col>
18 23 <el-col :span="11">
19   - <el-time-picker v-model="form.date2" type="fixed-time" placeholder="Pick a time" style="width: 100%;" />
  24 + <el-time-picker
  25 + v-model="form.date2"
  26 + type="fixed-time"
  27 + placeholder="Pick a time"
  28 + style="width: 100%;"
  29 + />
20 30 </el-col>
21 31 </el-form-item>
22 32 <el-form-item label="Instant delivery">
... ... @@ -52,33 +62,33 @@ export default {
52 62 data() {
53 63 return {
54 64 form: {
55   - name: '',
56   - region: '',
57   - date1: '',
58   - date2: '',
  65 + name: "",
  66 + region: "",
  67 + date1: "",
  68 + date2: "",
59 69 delivery: false,
60 70 type: [],
61   - resource: '',
62   - desc: ''
  71 + resource: "",
  72 + desc: ""
63 73 }
64   - }
  74 + };
65 75 },
66 76 methods: {
67 77 onSubmit() {
68   - this.$message('submit!')
  78 + this.$message("submit!");
69 79 },
70 80 onCancel() {
71 81 this.$message({
72   - message: 'cancel!',
73   - type: 'warning'
74   - })
  82 + message: "cancel!",
  83 + type: "warning"
  84 + });
75 85 }
76 86 }
77   -}
  87 +};
78 88 </script>
79 89  
80 90 <style scoped>
81   -.line{
  91 +.line {
82 92 text-align: center;
83 93 }
84 94 </style>
... ...
src/views/nested/menu1/menu1-1/index.vue
... ... @@ -5,3 +5,8 @@
5 5 </el-alert>
6 6 </div>
7 7 </template>
  8 +<template functional>
  9 + <div style="padding:30px;">
  10 + <el-alert :closable="false" title="menu 1-2-1" type="warning" />
  11 + </div>
  12 +</template>
8 13 \ No newline at end of file
... ...
src/views/table/index.vue
... ... @@ -8,73 +8,86 @@
8 8 fit
9 9 highlight-current-row
10 10 >
11   - <el-table-column align="center" label="ID" width="95">
12   - <template slot-scope="scope">
13   - {{ scope.$index }}
14   - </template>
  11 + <el-table-column align="center" label="用户id">
  12 + <template slot-scope="scope">{{ scope.$index }}</template>
  13 + </el-table-column>
  14 +
  15 + <el-table-column label="openid">
  16 + <template slot-scope="scope">{{ scope.row.openid }}</template>
15 17 </el-table-column>
16   - <el-table-column label="Title">
  18 +
  19 + <el-table-column label="昵称" width="110" align="center">
17 20 <template slot-scope="scope">
18   - {{ scope.row.title }}
  21 + <span>{{ scope.row.username }}</span>
19 22 </template>
20 23 </el-table-column>
21   - <el-table-column label="Author" width="110" align="center">
  24 +
  25 + <el-table-column label="头像" width="110" align="center">
  26 + <template slot-scope="scope">{{ scope.row.avatar }}</template>
  27 + </el-table-column>
  28 +
  29 + <el-table-column class-name="status-col" label="状态" align="center">
22 30 <template slot-scope="scope">
23   - <span>{{ scope.row.author }}</span>
  31 + <el-tag :type="scope.row.status | statusFilter">{{ scope.row.status }}</el-tag>
24 32 </template>
25 33 </el-table-column>
26   - <el-table-column label="Pageviews" width="110" align="center">
  34 +
  35 + <el-table-column align="center" prop="created_at" label="注册时间">
27 36 <template slot-scope="scope">
28   - {{ scope.row.pageviews }}
  37 + <i class="el-icon-time" />
  38 + <span>{{ scope.row.create_at }}</span>
29 39 </template>
30 40 </el-table-column>
31   - <el-table-column class-name="status-col" label="Status" width="110" align="center">
  41 + <el-table-column align="center" prop="created_at" label="成交记录">
32 42 <template slot-scope="scope">
33   - <el-tag :type="scope.row.status | statusFilter">{{ scope.row.status }}</el-tag>
  43 + <i class="el-icon-time" />
  44 + <span>{{ scope.row.pageviews }}</span>
34 45 </template>
35 46 </el-table-column>
36   - <el-table-column align="center" prop="created_at" label="Display_time" width="200">
  47 + <el-table-column align="center" prop="created_at" label="引流图">
37 48 <template slot-scope="scope">
38   - <i class="el-icon-time" />
39   - <span>{{ scope.row.display_time }}</span>
  49 + <span>
  50 + <el-button type="primary">子用户{{scope.row.pageviews}}</el-button>
  51 + </span>
40 52 </template>
41 53 </el-table-column>
42 54 </el-table>
  55 + <el-pagination background layout="prev, pager, next" :total="100"></el-pagination>
43 56 </div>
44 57 </template>
45 58  
46 59 <script>
47   -import { getList } from '@/api/table'
  60 +import { getList } from "@/api/table";
48 61  
49 62 export default {
50 63 filters: {
51 64 statusFilter(status) {
52 65 const statusMap = {
53   - published: 'success',
54   - draft: 'gray',
55   - deleted: 'danger'
56   - }
57   - return statusMap[status]
  66 + published: "success",
  67 + draft: "gray",
  68 + deleted: "danger"
  69 + };
  70 + return statusMap[status];
58 71 }
59 72 },
60 73 data() {
61 74 return {
62 75 list: null,
63 76 listLoading: true
64   - }
  77 + };
65 78 },
66 79 created() {
67   - this.fetchData()
  80 + this.fetchData();
68 81 },
69 82 methods: {
70 83 fetchData() {
71   - this.listLoading = true
  84 + this.listLoading = true;
72 85 getList().then(response => {
73   - console.log('----getList---', response)
74   - this.list = response.data.items
75   - this.listLoading = false
76   - })
  86 + console.log("----getList---", response);
  87 + this.list = response.data.items;
  88 + this.listLoading = false;
  89 + });
77 90 }
78 91 }
79   -}
  92 +};
80 93 </script>
... ...