Browse Source

feat: 🎸 v0.0.4发布

chenkl 4 years ago
parent
commit
a58dc1b1c2
38 changed files with 675 additions and 146 deletions
  1. 5 0
      README.md
  2. 17 1
      mock/role/admin-role.ts
  3. 16 0
      mock/role/test-role.ts
  4. 7 5
      package.json
  5. 133 0
      src/components/Avatars/index.vue
  6. 5 0
      src/components/Avatars/types.ts
  7. 4 1
      src/components/Detail/index.vue
  8. 69 0
      src/components/Highlight/index.vue
  9. 1 1
      src/components/Logo/index.vue
  10. 1 1
      src/components/ParentView/useCache.ts
  11. 1 1
      src/components/Screenfull/index.vue
  12. 1 1
      src/components/Setting/index.vue
  13. 2 2
      src/components/Sider/index.vue
  14. 2 2
      src/components/TagsView/index.vue
  15. 4 4
      src/components/UserInfo/index.vue
  16. 1 1
      src/pages/index/App.vue
  17. 1 1
      src/pages/index/layout/index.vue
  18. 5 2
      src/pages/index/layout/modules/Classic.vue
  19. 5 2
      src/pages/index/layout/modules/LeftTop.vue
  20. 3 2
      src/pages/index/layout/modules/Top.vue
  21. 2 2
      src/pages/index/permission.ts
  22. 82 57
      src/pages/index/router/index.ts
  23. 5 5
      src/pages/index/store/modules/permission.ts
  24. 2 2
      src/pages/index/store/modules/tagsView.ts
  25. 79 0
      src/pages/index/views/components-demo/avatars/index.vue
  26. 49 0
      src/pages/index/views/components-demo/highlight/index.vue
  27. 1 1
      src/pages/index/views/example-demo/example-dialog/api.ts
  28. 1 1
      src/pages/index/views/example-demo/example-page/api.ts
  29. 48 0
      src/pages/index/views/guide/index.vue
  30. 40 0
      src/pages/index/views/guide/steps.ts
  31. 1 1
      src/pages/index/views/login/api.ts
  32. 2 2
      src/pages/index/views/login/index.vue
  33. 1 1
      src/pages/index/views/role-demo/role/api.ts
  34. 2 2
      src/pages/index/views/role-demo/role/components/InfoWrite.vue
  35. 1 1
      src/pages/index/views/role-demo/user/api.ts
  36. 6 0
      tsconfig.json
  37. 3 11
      vue.config.js
  38. 67 33
      yarn.lock

+ 5 - 0
README.md

@@ -21,6 +21,8 @@
 
 - 多页配置
 
+- 引导页
+
 - 全局功能
   - 三种不同风格 layout 布局
   - 动态侧边栏(支持多级路由嵌套)
@@ -42,6 +44,9 @@
   - 弹窗
   - 显示更多
   - 详情组件
+  - 二维码组件
+  - 头像组
+  - 文字高亮
 
 - 表格
   - 基础表格

+ 17 - 1
mock/role/admin-role.ts

@@ -50,6 +50,14 @@ export const checkedNodes = [{
     'path': '/components-demo/qrcode',
     'title': '二维码组件',
     'name': 'QrcodeDemo'
+  }, {
+    'path': '/components-demo/avatars',
+    'title': '头像组',
+    'name': 'AvatarsDemo'
+  }, {
+    'path': '/components-demo/highlight',
+    'title': '文字高亮',
+    'name': 'HighlightDemo'
   }]
 }, {
   'path': '/components-demo/echarts',
@@ -99,6 +107,14 @@ export const checkedNodes = [{
   'path': '/components-demo/qrcode',
   'title': '二维码组件',
   'name': 'QrcodeDemo'
+}, {
+  'path': '/components-demo/avatars',
+  'title': '头像组',
+  'name': 'AvatarsDemo'
+}, {
+  'path': '/components-demo/highlight',
+  'title': '文字高亮',
+  'name': 'HighlightDemo'
 }, {
   'path': '/table-demo',
   'title': '表格',
@@ -415,7 +431,7 @@ export const checkedNodes = [{
 export const checkedkeys = ['/components-demo', '/components-demo/echarts', '/components-demo/preview',
   '/components-demo/button', '/components-demo/message', '/components-demo/count-to', '/components-demo/search',
   '/components-demo/editor', '/components-demo/markdown', '/components-demo/dialog', '/components-demo/more',
-  '/components-demo/detail', '/components-demo/qrcode', '/table-demo', '/table-demo/basic-table', '/table-demo/page-table',
+  '/components-demo/detail', '/components-demo/qrcode', '/components-demo/avatars', '/table-demo', '/table-demo/basic-table', '/table-demo/page-table',
   '/table-demo/stripe-table', '/table-demo/border-table', '/table-demo/state-table', '/table-demo/fixed-header',
   '/table-demo/fixed-column', '/table-demo/fixed-column-header', '/table-demo/fluid-height',
   '/table-demo/multi-header', '/table-demo/single-choice', '/table-demo/multiple-choice', '/table-demo/sort-table',

+ 16 - 0
mock/role/test-role.ts

@@ -105,6 +105,22 @@ export const checkedRoleNodes = [
         meta: {
           title: '二维码组件'
         }
+      },
+      {
+        path: 'avatars',
+        component: 'pages/index/views/components-demo/avatars/index',
+        name: 'AvatarsDemo',
+        meta: {
+          title: '头像组'
+        }
+      },
+      {
+        path: 'highlight',
+        component: 'pages/index/views/components-demo/highlight/index',
+        name: 'HighlightDemo',
+        meta: {
+          title: '文字高亮'
+        }
       }
     ]
   },

+ 7 - 5
package.json

@@ -1,6 +1,6 @@
 {
   "name": "vue-element-plus-admin-webpack",
-  "version": "0.1.0",
+  "version": "0.0.4",
   "private": true,
   "scripts": {
     "serve": "vue-cli-service serve",
@@ -20,8 +20,9 @@
     "clipboard": "^2.0.6",
     "core-js": "^3.6.5",
     "echarts": "^4.9.0",
-    "element-plus": "1.0.1-beta.26",
+    "element-plus": "1.0.2-beta.29",
     "highlight.js": "^10.4.0",
+    "intro.js": "^3.2.1",
     "lodash-es": "^4.17.15",
     "mitt": "^2.1.0",
     "mockjs": "^1.1.0",
@@ -32,8 +33,8 @@
     "qs": "^6.9.4",
     "screenfull": "^5.0.2",
     "vditor": "^3.7.0",
-    "vue": "3.0.4",
-    "vue-router": "4.0.0-rc.6",
+    "vue": "3.0.5",
+    "vue-router": "4.0.3",
     "vuex": "4.0.0-rc.2",
     "wangeditor": "4.5.4",
     "web-storage-cache": "^1.1.1"
@@ -44,6 +45,7 @@
     "@ls-lint/ls-lint": "^1.9.2",
     "@types/clipboard": "^2.0.1",
     "@types/echarts": "^4.9.1",
+    "@types/intro.js": "^3.0.0",
     "@types/lodash-es": "^4.17.3",
     "@types/mockjs": "^1.0.3",
     "@types/nprogress": "^0.2.0",
@@ -71,7 +73,7 @@
     "eslint-config-prettier": "^6.14.0",
     "eslint-plugin-prettier": "^3.1.4",
     "eslint-plugin-vue": "^7.0.0-0",
-    "husky": "^1.3.1",
+    "husky": "1.3.1",
     "less": "^3.0.4",
     "less-loader": "^5.0.0",
     "path": "^0.12.7",

+ 133 - 0
src/components/Avatars/index.vue

@@ -0,0 +1,133 @@
+<template>
+  <div class="avatars-wrap">
+    <template v-if="tooltip">
+      <el-tooltip
+        v-for="(item, $index) in avatarsData"
+        :key="$index"
+        :content="item.text"
+        effect="dark"
+        placement="top"
+      >
+        <div :class="showAvatar ? 'avatars-item-img' : ['avatars-item', `avatars-${item.type || 'default'}`]">
+          <el-avatar v-if="showAvatar" :size="40" :src="item.url">
+            <img :src="require('@/assets/img/avatar.png')">
+          </el-avatar>
+          <span v-else>{{ item.text.substr(0, 1) }}</span>
+        </div>
+      </el-tooltip>
+      <div v-if="max && data.length - max > 0" :class="['avatars-item', 'avatars-item-img']">
+        <span>+{{ data.length - max }}</span>
+      </div>
+    </template>
+    <template v-else>
+      <div
+        v-for="(item, $index) in avatarsData"
+        :key="$index"
+        :class="showAvatar ? 'avatars-item-img' : ['avatars-item', `avatars-${item.type || 'default'}`]"
+      >
+        <el-avatar v-if="showAvatar" :size="40" :src="item.url">
+          <img :src="require('@/assets/img/avatar.png')">
+        </el-avatar>
+        <span v-else>{{ item.text.substr(0, 1) }}</span>
+      </div>
+      <div v-if="max && data.length - max > 0" :class="['avatars-item', 'avatars-item-img']">
+        <span>+{{ data.length - max }}</span>
+      </div>
+    </template>
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent, PropType, computed } from 'vue'
+import { deepClone } from '@/utils'
+import { DataConfig } from './types'
+export default defineComponent({
+  name: 'Avatars',
+  props: {
+    // 展示的数据
+    data: {
+      type: Array as PropType<DataConfig[]>,
+      default: () => []
+    },
+    // 最大展示数量
+    max: {
+      type: Number as PropType<number>,
+      default: 0
+    },
+    // 是否使用头像
+    showAvatar: {
+      type: Boolean as PropType<boolean>,
+      default: false
+    },
+    // 是否显示完整名称
+    tooltip: {
+      type: Boolean as PropType<boolean>,
+      default: true
+    }
+  },
+  setup(props) {
+    const avatarsData = computed(() => {
+      if (props.max) {
+        if (props.data.length <= props.max) {
+          return props.data
+        } else {
+          const data = deepClone(props.data).splice(0, props.max)
+          return data
+        }
+      } else {
+        return props.data
+      }
+    })
+
+    return {
+      avatarsData
+    }
+  }
+})
+</script>
+
+<style lang="less" scoped>
+.avatars-wrap {
+  display: flex;
+  .avatars-item {
+    display: inline-block;
+    width: 40px;
+    height: 40px;
+    line-height: 40px;
+    border-radius: 50%;
+    border: 1px solid #fff;
+    text-align: center;
+    color: #fff;
+    background: #2d8cf0;
+  }
+  .avatars-item-img {
+    display: inline-block;
+    border-radius: 50%;
+    .el-avatar--circle {
+      border: 1px solid #fff;
+    }
+  }
+  .avatars-item-img + .avatars-item-img {
+    margin-left: -12px;
+  }
+  .avatars-item + .avatars-item {
+    margin-left: -12px;
+  }
+  .avatars-default {
+    color: #bae7ff;
+    background: #096dd9;
+  }
+  .avatars-success {
+    color: #f6ffed;
+    background: #52c41a;
+  }
+  .avatars-danger {
+    color: #fff1f0;
+    background: #f5222d;
+  }
+  .avatars-warning {
+    color: #fffbe6;
+    background: #faad14;
+  }
+}
+</style>

+ 5 - 0
src/components/Avatars/types.ts

@@ -0,0 +1,5 @@
+export interface DataConfig {
+  text: string
+  type?: string
+  url?: string
+}

+ 4 - 1
src/components/Detail/index.vue

@@ -22,7 +22,7 @@
         class="detail__content"
         :style="contentStyleObj"
       >
-        <el-row>
+        <el-row type="flex">
           <el-col
             v-for="(item, $index) in schema"
             :key="$index"
@@ -192,6 +192,9 @@ export default defineComponent({
     }
   }
   .detail__content {
+    @{deep}(.el-row) {
+      flex-wrap: wrap;
+    }
     .detail__content--flex {
       display: flex;
       height: 100%;

+ 69 - 0
src/components/Highlight/index.vue

@@ -0,0 +1,69 @@
+<script lang="ts">
+import { defineComponent, PropType, computed, h } from 'vue'
+export default defineComponent({
+  name: 'Highlight',
+  props: {
+    tag: {
+      type: String as PropType<string>,
+      default: 'span'
+    },
+    keys: {
+      type: Array as PropType<string[]>,
+      default: () => []
+    },
+    color: {
+      type: String as PropType<string>,
+      default: '#2d8cf0'
+    }
+  },
+  emits: ['click'],
+  setup(props, { emit }) {
+    const keyNodes = computed(() => {
+      return props.keys.map(key => {
+        return h('span', {
+          onClick: () => {
+            emit('click', key)
+          },
+          style: {
+            color: props.color,
+            cursor: 'pointer'
+          }
+        }, key)
+      })
+    })
+
+    function parseText(text: string) {
+      props.keys.forEach((key, index) => {
+        const regexp = new RegExp(key, 'g')
+        text = text.replace(regexp, `{{${index}}}`)
+      })
+      return text.split(/{{|}}/)
+    }
+
+    return {
+      keyNodes,
+      parseText
+    }
+  },
+  render(props: any) {
+    if (!props.$slots.default) return null
+    const node = props.$slots.default()[0].children
+    if (!node) {
+      console.warn('Highlight组件的插槽必须要是文本')
+      return props.$slots.default()[0]
+    }
+    const textArray = props.parseText(node)
+    const regexp = /^[0-9]*$/
+    const nodes = textArray.map((t: any) => {
+      if (regexp.test(t)) {
+        return props.keyNodes[Math.floor(t)] || t
+      }
+      return t
+    })
+    return h(props.tag, nodes)
+  }
+})
+</script>
+
+<style>
+</style>

+ 1 - 1
src/components/Logo/index.vue

@@ -7,7 +7,7 @@
 
 <script lang="ts">
 import { defineComponent, ref, watch, PropType, computed } from 'vue'
-import { appStore } from '_p/index/store/modules/app'
+import { appStore } from '_@/store/modules/app'
 
 export default defineComponent({
   name: 'Logo',

+ 1 - 1
src/components/ParentView/useCache.ts

@@ -1,6 +1,6 @@
 import { computed, ref, unref, ComponentInternalInstance, getCurrentInstance } from 'vue'
 
-import { tagsViewStore, PAGE_LAYOUT_KEY } from '_p/index/store/modules/tagsView'
+import { tagsViewStore, PAGE_LAYOUT_KEY } from '_@/store/modules/tagsView'
 
 import { useRouter } from 'vue-router'
 

+ 1 - 1
src/components/Screenfull/index.vue

@@ -1,6 +1,6 @@
 <template>
   <el-tooltip placement="bottom" :content="isFullscreen ? '退出全屏' : '全屏'">
-    <div style="height: 100%;" class="screenfull-svg" @click="click">
+    <div id="screenfull-container" style="height: 100%;" class="screenfull-svg" @click="click">
       <svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" />
     </div>
   </el-tooltip>

+ 1 - 1
src/components/Setting/index.vue

@@ -103,7 +103,7 @@
 
 <script lang="ts">
 import { defineComponent, computed, ref } from 'vue'
-import { appStore } from '_p/index/store/modules/app'
+import { appStore } from '_@/store/modules/app'
 export default defineComponent({
   name: 'Setting',
   setup() {

+ 2 - 2
src/components/Sider/index.vue

@@ -26,8 +26,8 @@
 <script lang="ts">
 import { defineComponent, computed, PropType } from 'vue'
 import { useRouter } from 'vue-router'
-import { permissionStore } from '_p/index/store/modules/permission'
-import { appStore } from '_p/index/store/modules/app'
+import { permissionStore } from '_@/store/modules/permission'
+import { appStore } from '_@/store/modules/app'
 import type { RouteRecordRaw } from 'vue-router'
 import SiderItem from './SiderItem.vue'
 import variables from '@/styles/variables.less'

+ 2 - 2
src/components/TagsView/index.vue

@@ -41,8 +41,8 @@
 import ScrollPane from './ScrollPane.vue'
 import path from 'path'
 import { defineComponent, ref, unref, computed, watch, onMounted, nextTick } from 'vue'
-import { tagsViewStore } from '_p/index/store/modules/tagsView'
-import { permissionStore } from '_p/index/store/modules/permission'
+import { tagsViewStore } from '_@/store/modules/tagsView'
+import { permissionStore } from '_@/store/modules/permission'
 import { useRouter } from 'vue-router'
 import type { RouteLocationNormalizedLoaded, RouteRecordRaw } from 'vue-router'
 

+ 4 - 4
src/components/UserInfo/index.vue

@@ -1,6 +1,6 @@
 <template>
   <el-dropdown class="avatar-container" trigger="hover">
-    <div>
+    <div id="user-container">
       <div class="avatar-wrapper">
         <img :src="require('@/assets/img/avatar.png')" class="user-avatar">
         <span class="name-item">管理员</span>
@@ -21,11 +21,11 @@
 
 <script lang="ts">
 import { defineComponent } from 'vue'
-import { resetRouter } from '_p/index/router'
+import { resetRouter } from '_@/router'
 import wsCache from '@/cache'
 import { useRouter } from 'vue-router'
-import { tagsViewStore } from '_p/index/store/modules/tagsView'
-import { appStore } from '_p/index/store/modules/app'
+import { tagsViewStore } from '_@/store/modules/tagsView'
+import { appStore } from '_@/store/modules/app'
 export default defineComponent({
   name: 'UserInfo',
   setup() {

+ 1 - 1
src/pages/index/App.vue

@@ -4,7 +4,7 @@
 
 <script lang="ts">
 import { defineComponent, computed } from 'vue'
-import { appStore } from '_p/index/store/modules/app'
+import { appStore } from '_@/store/modules/app'
 export default defineComponent({
   name: 'App',
   setup() {

+ 1 - 1
src/pages/index/layout/index.vue

@@ -9,7 +9,7 @@ import { defineComponent, computed } from 'vue'
 import Classic from './modules/Classic.vue'
 import Top from './modules/Top.vue'
 import LeftTop from './modules/LeftTop.vue'
-import { appStore } from '_p/index/store/modules/app'
+import { appStore } from '_@/store/modules/app'
 export default defineComponent({
   name: 'Layout',
   components: {

+ 5 - 2
src/pages/index/layout/modules/Classic.vue

@@ -2,6 +2,7 @@
   <div :class="classObj" class="app__wrap">
     <!-- Classic -->
     <div
+      id="sidebar__wrap"
       class="sidebar__wrap"
       :class="{'sidebar__wrap--collapsed': collapsed}"
     >
@@ -39,11 +40,12 @@
           >
             <hamburger
               v-if="showHamburger"
+              id="hamburger-container"
               :collapsed="collapsed"
               class="hover-container"
               @toggleClick="setCollapsed"
             />
-            <breadcrumb v-if="showBreadcrumb" />
+            <breadcrumb v-if="showBreadcrumb" id="breadcrumb-container" />
             <div v-if="showScreenfull || showUserInfo" class="navbar__wrap--right">
               <screenfull v-if="showScreenfull" class="hover-container screenfull-container" />
               <user-info v-if="showUserInfo" class="hover-container user-container" />
@@ -51,6 +53,7 @@
           </div>
           <div
             v-if="showTags"
+            id="tag-container"
             class="tags__wrap"
           >
             <tags-view />
@@ -70,7 +73,7 @@
 
 <script lang="ts">
 import { defineComponent, computed } from 'vue'
-import { appStore } from '_p/index/store/modules/app'
+import { appStore } from '_@/store/modules/app'
 
 import AppMain from '../components/AppMain.vue'
 import TagsView from '_c/TagsView/index.vue'

+ 5 - 2
src/pages/index/layout/modules/LeftTop.vue

@@ -2,6 +2,7 @@
   <div :class="classObj" class="app__wrap">
     <!-- Classic -->
     <div
+      id="sidebar__wrap"
       class="sidebar__wrap"
       :class="{'sidebar__wrap--collapsed': collapsed}"
     >
@@ -60,11 +61,12 @@
           >
             <hamburger
               v-if="showHamburger"
+              id="hamburger-container"
               :collapsed="collapsed"
               class="hover-container"
               @toggleClick="setCollapsed"
             />
-            <breadcrumb v-if="showBreadcrumb" />
+            <breadcrumb v-if="showBreadcrumb" id="breadcrumb-container" />
             <!-- <div v-if="showScreenfull || showUserInfo" class="navbar__wrap--right">
               <screenfull v-if="showScreenfull" class="hover-container screenfull-container" />
               <user-info v-if="showUserInfo" class="hover-container user-container" />
@@ -72,6 +74,7 @@
           </div>
           <div
             v-if="showTags"
+            id="tag-container"
             class="tags__wrap"
           >
             <tags-view />
@@ -91,7 +94,7 @@
 
 <script lang="ts">
 import { defineComponent, computed } from 'vue'
-import { appStore } from '_p/index/store/modules/app'
+import { appStore } from '_@/store/modules/app'
 
 import AppMain from '../components/AppMain.vue'
 import TagsView from '_c/TagsView/index.vue'

+ 3 - 2
src/pages/index/layout/modules/Top.vue

@@ -8,7 +8,7 @@
           :collapsed="collapsed"
         />
       </div>
-      <div class="sidebar__item--Top">
+      <div id="sidebar__wrap" class="sidebar__item--Top">
         <sider :layout="layout" mode="horizontal" />
       </div>
       <div>
@@ -59,6 +59,7 @@
           </div> -->
           <div
             v-if="showTags"
+            id="tag-container"
             class="tags__wrap"
           >
             <tags-view />
@@ -78,7 +79,7 @@
 
 <script lang="ts">
 import { defineComponent, computed } from 'vue'
-import { appStore } from '_p/index/store/modules/app'
+import { appStore } from '_@/store/modules/app'
 
 import AppMain from '../components/AppMain.vue'
 import TagsView from '_c/TagsView/index.vue'

+ 2 - 2
src/pages/index/permission.ts

@@ -4,7 +4,7 @@ import NProgress from 'nprogress' // 引入进度条
 
 import 'nprogress/nprogress.css' // 进度条样式
 
-import { appStore } from '_p/index/store/modules/app'
+import { appStore } from '_@/store/modules/app'
 
 import wsCache from '@/cache'
 
@@ -12,7 +12,7 @@ import getPageTitle from '@/utils/get-page-title'
 
 NProgress.configure({ showSpinner: false }) // NProgress configuration
 
-import { permissionStore } from '_p/index/store/modules/permission'
+import { permissionStore } from '_@/store/modules/permission'
 
 import type { RouteRecordRaw } from 'vue-router'
 

+ 82 - 57
src/pages/index/router/index.ts

@@ -57,7 +57,7 @@ export const constantRouterMap: AppRouteRecordRaw[] = [
   },
   {
     path: '/login',
-    component: () => import('_p/index/views/login/index.vue'),
+    component: () => import('_v/login/index.vue'),
     name: 'Login',
     meta: {
       hidden: true,
@@ -74,7 +74,7 @@ export const constantRouterMap: AppRouteRecordRaw[] = [
     children: [
       {
         path: 'dashboard',
-        component: () => import('_p/index/views/dashboard/index.vue'),
+        component: () => import('_v/dashboard/index.vue'),
         name: 'Dashboard',
         meta: {
           title: '首页',
@@ -95,6 +95,23 @@ export const constantRouterMap: AppRouteRecordRaw[] = [
         meta: { title: '文档', icon: 'documentation' }
       }
     ]
+  },
+  {
+    path: '/guide',
+    component: Layout,
+    name: 'Guide',
+    meta: {},
+    children: [
+      {
+        path: 'index',
+        component: () => import('_v/guide/index.vue'),
+        name: 'GuideDemo',
+        meta: {
+          title: '引导页',
+          icon: 'guide'
+        }
+      }
+    ]
   }
 ]
 
@@ -112,7 +129,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
     children: [
       {
         path: 'echarts',
-        component: () => import('_p/index/views/components-demo/echarts/index.vue'),
+        component: () => import('_v/components-demo/echarts/index.vue'),
         name: 'EchartsDemo',
         meta: {
           title: '图表'
@@ -120,7 +137,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'preview',
-        component: () => import('_p/index/views/components-demo/preview/index.vue'),
+        component: () => import('_v/components-demo/preview/index.vue'),
         name: 'PreviewDemo',
         meta: {
           title: '图片预览'
@@ -128,7 +145,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'button',
-        component: () => import('_p/index/views/components-demo/button/index.vue'),
+        component: () => import('_v/components-demo/button/index.vue'),
         name: 'ButtonDemo',
         meta: {
           title: '按钮'
@@ -136,7 +153,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'message',
-        component: () => import('_p/index/views/components-demo/message/index.vue'),
+        component: () => import('_v/components-demo/message/index.vue'),
         name: 'MessageDemo',
         meta: {
           title: '消息提示'
@@ -144,7 +161,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'count-to',
-        component: () => import('_p/index/views/components-demo/count-to/index.vue'),
+        component: () => import('_v/components-demo/count-to/index.vue'),
         name: 'CountToDemo',
         meta: {
           title: '数字动画'
@@ -152,7 +169,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'search',
-        component: () => import('_p/index/views/components-demo/search/index.vue'),
+        component: () => import('_v/components-demo/search/index.vue'),
         name: 'SearchDemo',
         meta: {
           title: '查询'
@@ -160,7 +177,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'editor',
-        component: () => import('_p/index/views/components-demo/editor/index.vue'),
+        component: () => import('_v/components-demo/editor/index.vue'),
         name: 'EditorDemo',
         meta: {
           title: '富文本编辑器'
@@ -168,7 +185,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'markdown',
-        component: () => import('_p/index/views/components-demo/markdown/index.vue'),
+        component: () => import('_v/components-demo/markdown/index.vue'),
         name: 'MarkdownDemo',
         meta: {
           title: 'markdown编辑器'
@@ -176,7 +193,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'dialog',
-        component: () => import('_p/index/views/components-demo/dialog/index.vue'),
+        component: () => import('_v/components-demo/dialog/index.vue'),
         name: 'DialogDemo',
         meta: {
           title: '弹窗'
@@ -184,7 +201,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'more',
-        component: () => import('_p/index/views/components-demo/more/index.vue'),
+        component: () => import('_v/components-demo/more/index.vue'),
         name: 'MoreDemo',
         meta: {
           title: '显示更多'
@@ -192,7 +209,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'detail',
-        component: () => import('_p/index/views/components-demo/detail/index.vue'),
+        component: () => import('_v/components-demo/detail/index.vue'),
         name: 'DetailDemo',
         meta: {
           title: '详情组件'
@@ -200,18 +217,34 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'qrcode',
-        component: () => import('_p/index/views/components-demo/qrcode/index.vue'),
+        component: () => import('_v/components-demo/qrcode/index.vue'),
         name: 'QrcodeDemo',
         meta: {
           title: '二维码组件'
         }
+      },
+      {
+        path: 'avatars',
+        component: () => import('_v/components-demo/avatars/index.vue'),
+        name: 'AvatarsDemo',
+        meta: {
+          title: '头像组'
+        }
+      },
+      {
+        path: 'highlight',
+        component: () => import('_v/components-demo/highlight/index.vue'),
+        name: 'HighlightDemo',
+        meta: {
+          title: '文字高亮'
+        }
       }
     ]
   },
   {
     path: '/table-demo',
     component: Layout,
-    redirect: '/table-demo/basic-usage',
+    redirect: '/table-demo/basic-table',
     name: 'TableDemo',
     meta: {
       title: '表格',
@@ -219,17 +252,9 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       alwaysShow: true
     },
     children: [
-      // {
-      //   path: 'test',
-      //   component: () => import('_p/index/views/table-demo/test'),
-      //   name: 'test',
-      //   meta: {
-      //     title: 'test'
-      //   }
-      // },
       {
         path: 'basic-table',
-        component: () => import('_p/index/views/table-demo/basic-table/index.vue'),
+        component: () => import('_v/table-demo/basic-table/index.vue'),
         name: 'BasicTable',
         meta: {
           title: '基础表格'
@@ -237,7 +262,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'page-table',
-        component: () => import('_p/index/views/table-demo/page-table/index.vue'),
+        component: () => import('_v/table-demo/page-table/index.vue'),
         name: 'PageTable',
         meta: {
           title: '分页表格'
@@ -245,7 +270,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'stripe-table',
-        component: () => import('_p/index/views/table-demo/stripe-table/index.vue'),
+        component: () => import('_v/table-demo/stripe-table/index.vue'),
         name: 'StripeTable',
         meta: {
           title: '带斑马纹表格'
@@ -253,7 +278,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'border-table',
-        component: () => import('_p/index/views/table-demo/border-table/index.vue'),
+        component: () => import('_v/table-demo/border-table/index.vue'),
         name: 'BorderTable',
         meta: {
           title: '带边框表格'
@@ -261,7 +286,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'state-table',
-        component: () => import('_p/index/views/table-demo/state-table/index.vue'),
+        component: () => import('_v/table-demo/state-table/index.vue'),
         name: 'StateTable',
         meta: {
           title: '带状态表格'
@@ -269,7 +294,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'fixed-header',
-        component: () => import('_p/index/views/table-demo/fixed-header/index.vue'),
+        component: () => import('_v/table-demo/fixed-header/index.vue'),
         name: 'FixedHeader',
         meta: {
           title: '固定表头'
@@ -277,7 +302,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'fixed-column',
-        component: () => import('_p/index/views/table-demo/fixed-column/index.vue'),
+        component: () => import('_v/table-demo/fixed-column/index.vue'),
         name: 'FixedColumn',
         meta: {
           title: '固定列'
@@ -285,7 +310,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'fixed-column-header',
-        component: () => import('_p/index/views/table-demo/fixed-column-header/index.vue'),
+        component: () => import('_v/table-demo/fixed-column-header/index.vue'),
         name: 'FixedColumnHeader',
         meta: {
           title: '固定列和表头'
@@ -293,7 +318,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'fluid-height',
-        component: () => import('_p/index/views/table-demo/fluid-height/index.vue'),
+        component: () => import('_v/table-demo/fluid-height/index.vue'),
         name: 'FluidHeight',
         meta: {
           title: '流体高度'
@@ -301,7 +326,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'multi-header',
-        component: () => import('_p/index/views/table-demo/multi-header/index.vue'),
+        component: () => import('_v/table-demo/multi-header/index.vue'),
         name: 'MultiHeader',
         meta: {
           title: '多级表头'
@@ -309,7 +334,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'single-choice',
-        component: () => import('_p/index/views/table-demo/single-choice/index.vue'),
+        component: () => import('_v/table-demo/single-choice/index.vue'),
         name: 'SingleChoice',
         meta: {
           title: '单选'
@@ -317,7 +342,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'multiple-choice',
-        component: () => import('_p/index/views/table-demo/multiple-choice/index.vue'),
+        component: () => import('_v/table-demo/multiple-choice/index.vue'),
         name: 'MultipleChoice',
         meta: {
           title: '多选'
@@ -325,7 +350,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'sort-table',
-        component: () => import('_p/index/views/table-demo/sort-table/index.vue'),
+        component: () => import('_v/table-demo/sort-table/index.vue'),
         name: 'SortTable',
         meta: {
           title: '排序'
@@ -333,7 +358,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'screen-table',
-        component: () => import('_p/index/views/table-demo/screen-table/index.vue'),
+        component: () => import('_v/table-demo/screen-table/index.vue'),
         name: 'ScreenTable',
         meta: {
           title: '筛选'
@@ -341,7 +366,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'expand-row',
-        component: () => import('_p/index/views/table-demo/expand-row/index.vue'),
+        component: () => import('_v/table-demo/expand-row/index.vue'),
         name: 'ExpandRow',
         meta: {
           title: '展开行'
@@ -349,7 +374,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'tree-and-load',
-        component: () => import('_p/index/views/table-demo/tree-and-load/index.vue'),
+        component: () => import('_v/table-demo/tree-and-load/index.vue'),
         name: 'TreeAndLoad',
         meta: {
           title: '树形数据与懒加载'
@@ -357,7 +382,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'custom-header',
-        component: () => import('_p/index/views/table-demo/custom-header/index.vue'),
+        component: () => import('_v/table-demo/custom-header/index.vue'),
         name: 'CustomHeader',
         meta: {
           title: '自定义表头'
@@ -365,7 +390,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'total-table',
-        component: () => import('_p/index/views/table-demo/total-table/index.vue'),
+        component: () => import('_v/table-demo/total-table/index.vue'),
         name: 'TotalTable',
         meta: {
           title: '表尾合计行'
@@ -373,7 +398,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'merge-table',
-        component: () => import('_p/index/views/table-demo/merge-table/index.vue'),
+        component: () => import('_v/table-demo/merge-table/index.vue'),
         name: 'MergeTable',
         meta: {
           title: '合并行或列'
@@ -381,7 +406,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'custom-index',
-        component: () => import('_p/index/views/table-demo/custom-index/index.vue'),
+        component: () => import('_v/table-demo/custom-index/index.vue'),
         name: 'CustomIndex',
         meta: {
           title: '自定义索引'
@@ -402,7 +427,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
     children: [
       {
         path: 'clipboard',
-        component: () => import('_p/index/views/directives-demo/clipboard/index.vue'),
+        component: () => import('_v/directives-demo/clipboard/index.vue'),
         name: 'ClipboardDemo',
         meta: {
           title: 'Clipboard'
@@ -423,7 +448,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
     children: [
       {
         path: 'watermark',
-        component: () => import('_p/index/views/hooks-demo/useWatermark/index.vue'),
+        component: () => import('_v/hooks-demo/useWatermark/index.vue'),
         name: 'UseWatermarkDemo',
         meta: {
           title: 'UseWaterMark'
@@ -431,7 +456,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'useScrollTo',
-        component: () => import('_p/index/views/hooks-demo/useScrollTo/index.vue'),
+        component: () => import('_v/hooks-demo/useScrollTo/index.vue'),
         name: 'UseScrollToDemo',
         meta: {
           title: 'UseScrollTo'
@@ -447,7 +472,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
     children: [
       {
         path: 'index',
-        component: () => import('_p/index/views/icons/index.vue'),
+        component: () => import('_v/icons/index.vue'),
         name: 'Icons',
         meta: {
           title: '图标',
@@ -488,7 +513,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
               {
                 path: 'menu1-1-1',
                 name: 'Menu111Demo',
-                component: () => import('_p/index/views/level/Menu111.vue'),
+                component: () => import('_v/level/Menu111.vue'),
                 meta: {
                   title: 'Menu1-1-1'
                 }
@@ -498,7 +523,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
           {
             path: 'menu1-2',
             name: 'Menu12Demo',
-            component: () => import('_p/index/views/level/Menu12.vue'),
+            component: () => import('_v/level/Menu12.vue'),
             meta: {
               title: 'Menu1-2'
             }
@@ -508,7 +533,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       {
         path: 'menu2',
         name: 'Menu2Demo',
-        component: () => import('_p/index/views/level/Menu2.vue'),
+        component: () => import('_v/level/Menu2.vue'),
         meta: {
           title: 'Menu2'
         }
@@ -528,7 +553,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
     children: [
       {
         path: 'example-dialog',
-        component: () => import('_p/index/views/example-demo/example-dialog/index.vue'),
+        component: () => import('_v/example-demo/example-dialog/index.vue'),
         name: 'ExampleDialog',
         meta: {
           title: '列表综合实例-弹窗'
@@ -536,7 +561,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'example-page',
-        component: () => import('_p/index/views/example-demo/example-page/index.vue'),
+        component: () => import('_v/example-demo/example-page/index.vue'),
         name: 'ExamplePage',
         meta: {
           title: '列表综合实例-页面'
@@ -544,7 +569,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'example-add',
-        component: () => import('_p/index/views/example-demo/example-page/example-add.vue'),
+        component: () => import('_v/example-demo/example-page/example-add.vue'),
         name: 'ExampleAdd',
         meta: {
           title: '列表综合实例-新增',
@@ -557,7 +582,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'example-edit',
-        component: () => import('_p/index/views/example-demo/example-page/example-edit.vue'),
+        component: () => import('_v/example-demo/example-page/example-edit.vue'),
         name: 'ExampleEdit',
         meta: {
           title: '列表综合实例-编辑',
@@ -570,7 +595,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'example-detail',
-        component: () => import('_p/index/views/example-demo/example-page/example-detail.vue'),
+        component: () => import('_v/example-demo/example-page/example-detail.vue'),
         name: 'ExampleDetail',
         meta: {
           title: '列表综合实例-详情',
@@ -596,7 +621,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
     children: [
       {
         path: 'user',
-        component: () => import('_p/index/views/role-demo/user/index.vue'),
+        component: () => import('_v/role-demo/user/index.vue'),
         name: 'User',
         meta: {
           title: '用户管理'
@@ -604,7 +629,7 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
       },
       {
         path: 'role',
-        component: () => import('_p/index/views/role-demo/role/index.vue'),
+        component: () => import('_v/role-demo/role/index.vue'),
         name: 'Role',
         meta: {
           title: '角色管理'

+ 5 - 5
src/pages/index/store/modules/permission.ts

@@ -1,17 +1,17 @@
-import { asyncRouterMap, constantRouterMap } from '_p/index/router'
+import { asyncRouterMap, constantRouterMap } from '_@/router'
 import { deepClone } from '@/utils'
 import store from '../index'
 import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-decorators'
-import { AppRouteRecordRaw } from '_p/index/router/types'
+import { AppRouteRecordRaw } from '_@/router/types'
 import wsCache from '@/cache'
 import { isExternal } from '@/utils/validate'
 import path from 'path'
-import { getParentLayout } from '_p/index/router/utils'
+import { getParentLayout } from '_@/router/utils'
 
-import { appStore } from '_p/index/store/modules/app'
+import { appStore } from '_@/store/modules/app'
 
 /* Layout */
-const Layout = () => import('_p/index/layout/index.vue')
+const Layout = () => import('_@/layout/index.vue')
 
 export interface PermissionState {
   routers: AppRouteRecordRaw[]

+ 2 - 2
src/pages/index/store/modules/tagsView.ts

@@ -1,8 +1,8 @@
 import store from '../index'
-import router from '_p/index/router'
+import router from '_@/router'
 import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-decorators'
 import type { RouteLocationNormalizedLoaded } from 'vue-router'
-import { getRoute } from '_p/index/router/utils'
+import { getRoute } from '_@/router/utils'
 
 export const PAGE_LAYOUT_KEY = '__PAGE_LAYOUT__'
 

+ 79 - 0
src/pages/index/views/components-demo/avatars/index.vue

@@ -0,0 +1,79 @@
+<template>
+  <div>
+    <el-alert
+      effect="dark"
+      :closable="false"
+      title="头像组组件 -- 基础用法"
+      type="info"
+      style="margin-bottom: 20px;"
+    />
+    <avatars :data="data" />
+
+    <el-alert
+      effect="dark"
+      :closable="false"
+      title="头像组组件 -- 不显示tooltip"
+      type="info"
+      style="margin-bottom: 20px;margin-top: 20px;"
+    />
+    <avatars :data="data" :tooltip="false" />
+
+    <el-alert
+      effect="dark"
+      :closable="false"
+      title="头像组组件 -- 最多展示5"
+      type="info"
+      style="margin-bottom: 20px;margin-top: 20px;"
+    />
+    <avatars :data="data" :max="5" />
+
+    <el-alert
+      effect="dark"
+      :closable="false"
+      title="头像组组件 -- 展示头像"
+      type="info"
+      style="margin-bottom: 20px;margin-top: 20px;"
+    />
+    <avatars show-avatar :data="data1" />
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent, ref } from 'vue'
+import Avatars from '_c/Avatars/index.vue'
+export default defineComponent({
+  name: 'AvatarsDemo',
+  components: {
+    Avatars
+  },
+  setup() {
+    const data = ref<any[]>([
+      { text: '陈某某' },
+      { text: '李某某', type: 'success' },
+      { text: '张某某', type: 'danger' },
+      { text: '王某某', type: 'warning' },
+      { text: '龙某某' },
+      { text: '孙某某' },
+      { text: '刘某某' },
+      { text: '赵某某' }
+    ])
+    const data1 = ref<any[]>([
+      { text: '陈某某', url: 'https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2863969516,2611770076&fm=26&gp=0.jpg' },
+      { text: '李某某', url: 'https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=465970198,3877503753&fm=26&gp=0.jpg' },
+      { text: '张某某', url: 'https://dss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1857202600,3614139084&fm=26&gp=0.jpg' },
+      { text: '王某某', url: 'https://dss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1444080181,4150129244&fm=26&gp=0.jpg' },
+      { text: '龙某某', url: 'https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2469786567,2163872639&fm=26&gp=0.jpg' },
+      { text: '孙某某', url: 'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=4119236579,869456058&fm=26&gp=0.jpg' },
+      { text: '刘某某', url: 'xxxxx' },
+      { text: '赵某某' }
+    ])
+
+    return {
+      data, data1
+    }
+  }
+})
+</script>
+
+<style>
+</style>

+ 49 - 0
src/pages/index/views/components-demo/highlight/index.vue

@@ -0,0 +1,49 @@
+<template>
+  <div>
+    <el-alert
+      effect="dark"
+      :closable="false"
+      title="文字高亮组件 -- 基础用法"
+      type="info"
+      style="margin-bottom: 20px;"
+    />
+    <highlight :keys="['vue-element-admin 2.0', 'vue-element-admin', 'iview-admin']">
+      vue-element-admin 2.0是一个基于vue2.x、vue-cli4.x、element-ui的后台解决方案,借鉴了vue-element-admin和iview-admin的写法和优点。内置了动态路由,权限验证,典型的业务模型,丰富的功能组件,并且提供了多页配置,开箱即用,可以用来作为项目的启动模版。它可以帮助你快速搭建企业级中后台产品原型,也可以作为一个示例,用于学习。
+    </highlight>
+
+    <el-alert
+      effect="dark"
+      :closable="false"
+      title="文字高亮组件 -- 点击事件"
+      type="info"
+      style="margin-bottom: 20px;margin-top: 20px;"
+    />
+    <highlight :keys="['vue-element-admin 2.0', 'vue-element-admin', 'iview-admin']" @click="keyClick">
+      vue-element-admin 2.0是一个基于vue2.x、vue-cli4.x、element-ui的后台解决方案,借鉴了vue-element-admin和iview-admin的写法和优点。内置了动态路由,权限验证,典型的业务模型,丰富的功能组件,并且提供了多页配置,开箱即用,可以用来作为项目的启动模版。它可以帮助你快速搭建企业级中后台产品原型,也可以作为一个示例,用于学习。
+    </highlight>
+  </div>
+</template>
+
+<script lang="ts">
+import Highlight from '_c/Highlight/index.vue'
+import { defineComponent } from 'vue'
+import { Message } from '_c/Message'
+export default defineComponent({
+  // name: 'HighlightDemo',
+  components: {
+    Highlight
+  },
+  setup() {
+    function keyClick(key: string) {
+      Message.success(key)
+    }
+
+    return {
+      keyClick
+    }
+  }
+})
+</script>
+
+<style>
+</style>

+ 1 - 1
src/pages/index/views/example-demo/example-dialog/api.ts

@@ -1,4 +1,4 @@
-import { fetch } from '_p/index/axios-config/axios'
+import { fetch } from '_@/axios-config/axios'
 
 interface PropsData {
   params?: any

+ 1 - 1
src/pages/index/views/example-demo/example-page/api.ts

@@ -1,4 +1,4 @@
-import { fetch } from '_p/index/axios-config/axios'
+import { fetch } from '_@/axios-config/axios'
 
 interface PropsData {
   params?: any

+ 48 - 0
src/pages/index/views/guide/index.vue

@@ -0,0 +1,48 @@
+<template>
+  <div>
+    <el-alert
+      effect="dark"
+      :closable="false"
+      title=" 引导页对于一些第一次进入项目的人很有用,你可以简单介绍下项目的功能。引导页基于 intro.js"
+      type="info"
+      style="margin-bottom: 20px;"
+    />
+    <el-button type="primary" @click.prevent.stop="guide">
+      开始引导
+    </el-button>
+  </div>
+</template>
+
+<script lang="ts">
+import IntroJs from 'intro.js'
+import 'intro.js/introjs.css'
+import steps from './steps'
+import { defineComponent, onMounted, ref } from 'vue'
+export default defineComponent({
+  name: 'GuideDemo',
+  setup() {
+    const driver = ref<any>(null)
+    onMounted(() => {
+      driver.value = new (IntroJs as any)()
+      driver.value.setOptions({
+        prevLabel: '上一步',
+        nextLabel: '下一步',
+        skipLabel: '跳过',
+        doneLabel: '结束',
+        steps
+      })
+    })
+
+    function guide() {
+      driver.value.start()
+    }
+
+    return {
+      guide
+    }
+  }
+})
+</script>
+
+<style>
+</style>

+ 40 - 0
src/pages/index/views/guide/steps.ts

@@ -0,0 +1,40 @@
+const steps = [
+  {
+    element: '#sidebar__wrap',
+    title: '菜单栏',
+    intro: '以路由的结构渲染的菜单栏',
+    position: 'right'
+  },
+  {
+    element: '#hamburger-container',
+    title: '展开缩收',
+    intro: '用于展开和缩放菜单栏',
+    position: 'bottom'
+  },
+  {
+    element: '#breadcrumb-container',
+    title: '面包屑',
+    intro: '用于记录当前路由结构',
+    position: 'bottom'
+  },
+  {
+    element: '#screenfull-container',
+    title: '是否全屏',
+    intro: '用于设置是否全屏',
+    position: 'left'
+  },
+  {
+    element: '#user-container',
+    title: '用户信息',
+    intro: '用于展示用户',
+    position: 'left'
+  },
+  {
+    element: '#tag-container',
+    title: '标签页',
+    intro: '用于记录路由历史记录',
+    position: 'bottom'
+  }
+]
+
+export default steps

+ 1 - 1
src/pages/index/views/login/api.ts

@@ -1,4 +1,4 @@
-import { fetch } from '_p/index/axios-config/axios'
+import { fetch } from '_@/axios-config/axios'
 
 interface PropsData {
   params?: any

+ 2 - 2
src/pages/index/views/login/index.vue

@@ -60,8 +60,8 @@
 import { defineComponent, ref, unref, reactive, watch } from 'vue'
 import { useRouter } from 'vue-router'
 import type { RouteRecordRaw } from 'vue-router'
-import { permissionStore } from '_p/index/store/modules/permission'
-import { appStore } from '_p/index/store/modules/app'
+import { permissionStore } from '_@/store/modules/permission'
+import { appStore } from '_@/store/modules/app'
 import wsCache from '@/cache'
 import { ElNotification } from 'element-plus'
 

+ 1 - 1
src/pages/index/views/role-demo/role/api.ts

@@ -1,4 +1,4 @@
-import { fetch } from '_p/index/axios-config/axios'
+import { fetch } from '_@/axios-config/axios'
 
 interface PropsData {
   params?: any

+ 2 - 2
src/pages/index/views/role-demo/role/components/InfoWrite.vue

@@ -40,8 +40,8 @@
 import path from 'path'
 import { defineComponent, PropType, ref, reactive, nextTick, unref } from 'vue'
 import { setRoleApi, getRoleDetApi } from '../api'
-import { asyncRouterMap } from '_p/index/router'
-import { AppRouteRecordRaw } from '_p/index/router/types'
+import { asyncRouterMap } from '_@/router'
+import { AppRouteRecordRaw } from '_@/router/types'
 import { isExternal } from '@/utils/validate'
 import { Message } from '_c/Message'
 

+ 1 - 1
src/pages/index/views/role-demo/user/api.ts

@@ -1,4 +1,4 @@
-import { fetch } from '_p/index/axios-config/axios'
+import { fetch } from '_@/axios-config/axios'
 
 interface PropsData {
   params?: any

+ 6 - 0
tsconfig.json

@@ -29,6 +29,12 @@
       "_c/*": [
         "src/components/*"
       ],
+      "_@/*": [
+        "src/pages/index/*"
+      ],
+      "_v/*": [
+        "src/pages/index/views/*"
+      ],
       "_p/*": [
         "src/pages/*"
       ]

+ 3 - 11
vue.config.js

@@ -37,8 +37,6 @@ glob.sync('./src/pages/**/main.ts').forEach((entry) => {
 
 projectName ? entryPages[projectName] = pages[projectName] : entryPages = pages
 
-const Timestamp = new Date().getTime()
-
 const vueConfig = {
   pages: entryPages,
   publicPath: './',
@@ -59,7 +57,8 @@ const vueConfig = {
     config.resolve.alias
       .set('@', resolve('src'))
       .set('_c', resolve('src/components'))
-      .set('_p', resolve('src/pages'))
+      .set('_@', resolve('src/pages/index'))
+      .set('_v', resolve('src/pages/index/views'))
       // .set('_pd1', resolve('src/pages/demo1'))
       // .set('_pd1v', resolve('src/pages/demo1/views'))
 
@@ -168,20 +167,13 @@ const vueConfig = {
     })
   },
   configureWebpack: {
-    output: {
-      filename: `js/[name].[hash].${Timestamp}.js`,
-      chunkFilename: `js/[name].[hash].${Timestamp}.js`
-    }
+    
   },
   css: {
     loaderOptions: {
       less: {
         javascriptEnabled: true
       }
-    },
-    extract: {
-      filename: `css/[name].[hash].${Timestamp}.css`,
-      chunkFilename: `css/[name].[hash].${Timestamp}.css`
     }
   },
   // 跨域代理

+ 67 - 33
yarn.lock

@@ -1196,6 +1196,11 @@
   dependencies:
     "@types/node" "*"
 
+"@types/intro.js@^3.0.0":
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/@types/intro.js/-/intro.js-3.0.0.tgz#27ae56f313ebef75c21a957367d1cfcd6b1a6f77"
+  integrity sha512-XbL3Y3jW82vQlf9L4gGOhnqsV9rM5Hs6LDe9hcXRsJj4j+NH5WnHzbRHfApSfLQGffHyCoKcJDaJbDHVptqLLA==
+
 "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6":
   version "7.0.6"
   resolved "https://registry.npm.taobao.org/@types/json-schema/download/@types/json-schema-7.0.6.tgz?cache=0&sync_timestamp=1605053861867&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fjson-schema%2Fdownload%2F%40types%2Fjson-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
@@ -1686,6 +1691,17 @@
     estree-walker "^2.0.1"
     source-map "^0.6.1"
 
+"@vue/compiler-core@3.0.5":
+  version "3.0.5"
+  resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.0.5.tgz#a6e54cabe9536e74c6513acd2649f311af1d43ac"
+  integrity sha512-iFXwk2gmU/GGwN4hpBwDWWMLvpkIejf/AybcFtlQ5V1ur+5jwfBaV0Y1RXoR6ePfBPJixtKZ3PmN+M+HgMAtfQ==
+  dependencies:
+    "@babel/parser" "^7.12.0"
+    "@babel/types" "^7.12.0"
+    "@vue/shared" "3.0.5"
+    estree-walker "^2.0.1"
+    source-map "^0.6.1"
+
 "@vue/compiler-dom@3.0.4":
   version "3.0.4"
   resolved "https://registry.npm.taobao.org/@vue/compiler-dom/download/@vue/compiler-dom-3.0.4.tgz#834fd4b15c5698cf9f4505c2bfbccca058a843eb"
@@ -1694,6 +1710,14 @@
     "@vue/compiler-core" "3.0.4"
     "@vue/shared" "3.0.4"
 
+"@vue/compiler-dom@3.0.5":
+  version "3.0.5"
+  resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.0.5.tgz#7885a13e6d18f64dde8ebceec052ed2c102696c2"
+  integrity sha512-HSOSe2XSPuCkp20h4+HXSiPH9qkhz6YbW9z9ZtL5vef2T2PMugH7/osIFVSrRZP/Ul5twFZ7MIRlp8tPX6e4/g==
+  dependencies:
+    "@vue/compiler-core" "3.0.5"
+    "@vue/shared" "3.0.5"
+
 "@vue/compiler-sfc@^3.0.3":
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.0.4.tgz#2119fe1e68d2c268aafa20461c82c139a9adf8e0"
@@ -1752,28 +1776,28 @@
   resolved "https://registry.npm.taobao.org/@vue/preload-webpack-plugin/download/@vue/preload-webpack-plugin-1.1.2.tgz#ceb924b4ecb3b9c43871c7a429a02f8423e621ab"
   integrity sha1-zrkktOyzucQ4ccekKaAvhCPmIas=
 
-"@vue/reactivity@3.0.4":
-  version "3.0.4"
-  resolved "https://registry.npm.taobao.org/@vue/reactivity/download/@vue/reactivity-3.0.4.tgz#b6599dd8271a745960a03f05744ccf7991ba5d8d"
-  integrity sha1-tlmd2CcadFlgoD8FdEzPeZG6XY0=
+"@vue/reactivity@3.0.5":
+  version "3.0.5"
+  resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.0.5.tgz#e3789e4d523d845f9ae0b4d770e2b45594742fd2"
+  integrity sha512-3xodUE3sEIJgS7ntwUbopIpzzvi7vDAOjVamfb2l+v1FUg0jpd3gf62N2wggJw3fxBMr+QvyxpD+dBoxLsmAjw==
   dependencies:
-    "@vue/shared" "3.0.4"
+    "@vue/shared" "3.0.5"
 
-"@vue/runtime-core@3.0.4":
-  version "3.0.4"
-  resolved "https://registry.npm.taobao.org/@vue/runtime-core/download/@vue/runtime-core-3.0.4.tgz#a5b9a001560b1fd8c01a43f68b764c555de7836c"
-  integrity sha1-pbmgAVYLH9jAGkP2i3ZMVV3ng2w=
+"@vue/runtime-core@3.0.5":
+  version "3.0.5"
+  resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.0.5.tgz#da6331d5f300d5794e9e0ebdc8a8bd72a9e19962"
+  integrity sha512-Cnyi2NqREwOLcTEsIi1DQX1hHtkVj4eGm4hBG7HhokS05DqpK4/80jG6PCCnCH9rIJDB2FqtaODX397210plXg==
   dependencies:
-    "@vue/reactivity" "3.0.4"
-    "@vue/shared" "3.0.4"
+    "@vue/reactivity" "3.0.5"
+    "@vue/shared" "3.0.5"
 
-"@vue/runtime-dom@3.0.4":
-  version "3.0.4"
-  resolved "https://registry.npm.taobao.org/@vue/runtime-dom/download/@vue/runtime-dom-3.0.4.tgz#6f81aec545f24511d2c28a315aa3391420b69c68"
-  integrity sha1-b4GuxUXyRRHSwooxWqM5FCC2nGg=
+"@vue/runtime-dom@3.0.5":
+  version "3.0.5"
+  resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.0.5.tgz#1ce2c9c449e26ab06963da0064096e882a7a8935"
+  integrity sha512-iilX1KySeIzHHtErT6Y44db1rhWK5tAI0CiJIPr+SJoZ2jbjoOSE6ff/jfIQakchbm1d6jq6VtRVnp5xYdOXKA==
   dependencies:
-    "@vue/runtime-core" "3.0.4"
-    "@vue/shared" "3.0.4"
+    "@vue/runtime-core" "3.0.5"
+    "@vue/shared" "3.0.5"
     csstype "^2.6.8"
 
 "@vue/shared@3.0.4":
@@ -1781,6 +1805,11 @@
   resolved "https://registry.npm.taobao.org/@vue/shared/download/@vue/shared-3.0.4.tgz#6dc50f593bdfdeaa6183d1dbc15e2d45e7c6b8b3"
   integrity sha1-bcUPWTvf3qphg9HbwV4tRefGuLM=
 
+"@vue/shared@3.0.5":
+  version "3.0.5"
+  resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.0.5.tgz#c131d88bd6713cc4d93b3bb1372edb1983225ff0"
+  integrity sha512-gYsNoGkWejBxNO6SNRjOh/xKeZ0H0V+TFzaPzODfBjkAIb0aQgBuixC1brandC/CDJy1wYPwSoYrXpvul7m6yw==
+
 "@vue/web-component-wrapper@^1.2.0":
   version "1.2.0"
   resolved "https://registry.npm.taobao.org/@vue/web-component-wrapper/download/@vue/web-component-wrapper-1.2.0.tgz#bb0e46f1585a7e289b4ee6067dcc5a6ae62f1dd1"
@@ -3992,10 +4021,10 @@ electron-to-chromium@^1.3.621:
   resolved "https://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.622.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felectron-to-chromium%2Fdownload%2Felectron-to-chromium-1.3.622.tgz#9726bd2e67a5462154750ce9701ca6af07d07877"
   integrity sha1-lya9LmelRiFUdQzpcBymrwfQeHc=
 
-element-plus@1.0.1-beta.26:
-  version "1.0.1-beta.26"
-  resolved "https://registry.yarnpkg.com/element-plus/-/element-plus-1.0.1-beta.26.tgz#f24181aab2569b62ca01e63541209b70d524b8ab"
-  integrity sha512-nFzkn31AlZ+bXjnAAeXRoewesC57fI6yaUbxZaE+f1maj9ll5dbtiwk6petJhYvjQ3si4fN3A9P/qZA3ZPeyMg==
+element-plus@1.0.2-beta.29:
+  version "1.0.2-beta.29"
+  resolved "https://registry.yarnpkg.com/element-plus/-/element-plus-1.0.2-beta.29.tgz#0ce640e07a1fdfd89a75bfacb2006a0899a6b316"
+  integrity sha512-wJKXQS58OXOBzOViQ44LfvauitlSx7HSZ3DAAgShZL3tUTnXX0AQE6w+UISAwql3lp2g93M3Yd+JMNnt8VpAag==
   dependencies:
     "@popperjs/core" "^2.4.4"
     async-validator "^3.4.0"
@@ -5372,7 +5401,7 @@ human-signals@^1.1.1:
   resolved "https://registry.npm.taobao.org/human-signals/download/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
   integrity sha1-xbHNFPUK6uCatsWf5jujOV/k36M=
 
-husky@^1.3.1:
+husky@1.3.1:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/husky/-/husky-1.3.1.tgz#26823e399300388ca2afff11cfa8a86b0033fae0"
   integrity sha512-86U6sVVVf4b5NYSZ0yvv88dRgBSSXXmHaiq5pP4KDj5JVzdwKgBjEtUPOm8hcoytezFwbU+7gotXNhpHdystlg==
@@ -5558,6 +5587,11 @@ internal-ip@^4.3.0:
     default-gateway "^4.2.0"
     ipaddr.js "^1.9.0"
 
+intro.js@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/intro.js/-/intro.js-3.2.1.tgz#fb13f03c13d54aab8485d538a719fe4af0b7bf36"
+  integrity sha512-empgAlW/vlIEAZWw19rLMR+1J75sw6bvjqrQd9fhgXJnV/ds0bzASil3k5fCWSJeVBKXFbLlWJ3nvtimDmTIFw==
+
 ip-regex@^2.1.0:
   version "2.1.0"
   resolved "https://registry.npm.taobao.org/ip-regex/download/ip-regex-2.1.0.tgz?cache=0&sync_timestamp=1601334312409&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fip-regex%2Fdownload%2Fip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
@@ -9962,10 +9996,10 @@ vue-loader@^15.9.2:
     vue-hot-reload-api "^2.3.0"
     vue-style-loader "^4.1.0"
 
-vue-router@4.0.0-rc.6:
-  version "4.0.0-rc.6"
-  resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.0.0-rc.6.tgz#8fa9e2d612c28ccf9b2bfa9421052932808ce24b"
-  integrity sha512-hVHC8A4/0yku1Z6+oUtX9odeHv78XwDI7putt1hd7os27P7mLabkjArN7f3TI3e/cz17MxAUz5Yp+m8ZE3sPsw==
+vue-router@4.0.3:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.0.3.tgz#8b26050c88b2dec7e27a88835f71046b365823ec"
+  integrity sha512-AD1OjtVPyQHTSpoRsEGfPpxRQwhAhxcacOYO3zJ3KNkYP/r09mileSp6kdMQKhZWP2cFsPR3E2M3PZguSN5/ww==
 
 vue-style-loader@^4.1.0, vue-style-loader@^4.1.2:
   version "4.1.2"
@@ -9980,14 +10014,14 @@ vue-template-es2015-compiler@^1.9.0:
   resolved "https://registry.npm.taobao.org/vue-template-es2015-compiler/download/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
   integrity sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=
 
-vue@3.0.4:
-  version "3.0.4"
-  resolved "https://registry.yarnpkg.com/vue/-/vue-3.0.4.tgz#872c65c143f5717bd5387c61613d9f55f4cc0f43"
-  integrity sha512-2o+AiQF8sAupyhbyl3oxVCl3WCwC/n5NI7VMM+gVQ231qvSB8eI7sCBloloqDJK6yA367EEtmRSeSCf4sxCC+A==
+vue@3.0.5:
+  version "3.0.5"
+  resolved "https://registry.yarnpkg.com/vue/-/vue-3.0.5.tgz#de1b82eba24abfe71e0970fc9b8d4b2babdc3fe1"
+  integrity sha512-TfaprOmtsAfhQau7WsomXZ8d9op/dkQLNIq8qPV3A0Vxs6GR5E+c1rfJS1SDkXRQj+dFyfnec7+U0Be1huiScg==
   dependencies:
-    "@vue/compiler-dom" "3.0.4"
-    "@vue/runtime-dom" "3.0.4"
-    "@vue/shared" "3.0.4"
+    "@vue/compiler-dom" "3.0.5"
+    "@vue/runtime-dom" "3.0.5"
+    "@vue/shared" "3.0.5"
 
 vuex-module-decorators@^1.0.1:
   version "1.0.1"