scorpio 2 years ago
parent
commit
92ef3855b5

+ 1 - 0
package.json

@@ -13,6 +13,7 @@
     "animate.css": "^4.1.1",
     "element-plus": "^2.2.9",
     "pinia": "^2.0.16",
+    "pinia-plugin-persistedstate": "^2.1.1",
     "vue": "^3.2.37",
     "vue-router": "^4.1.2"
   },

+ 67 - 67
src/api/fetch.js

@@ -3,86 +3,86 @@
  */
 import axios from 'axios'
 import router from '../router'
-import { removeToken, getToken} from "../utils/auth";
+import { removeToken, getToken } from '../utils/auth'
 
 axios.defaults.baseURL = ''
 
 axios.interceptors.request.use(config => {
-    config.headers.token = getToken()
-    // 小程序里用m的页面
-    config.headers.Platform = 'pc'
-    if (getToken() === null || getToken() === undefined) {
-        delete config.headers.token
-    }
-    return config
+  config.headers.token = getToken()
+  // 小程序里用m的页面
+  config.headers.Platform = 'pc'
+  if (getToken() === null || getToken() === undefined) {
+    delete config.headers.token
+  }
+  return config
 }, err => {
-    return Promise.reject(err)
+  return Promise.reject(err)
 })
 
 // insurance 保险 502 503 504时兜底的
-function fetch(url = '', params = {}, method = 'get', contentType = 'form', insurance, timeout = 15000) {
-    contentType === 'form' && (contentType = 'application/x-www-form-urlencoded')
-    contentType === 'json' && (contentType = 'application/json')
-    contentType === 'file' && (contentType = 'multipart/form-data')
-    let query = []
-    for (let k in params) {
-        query.push(k + '=' + params[k])
-    }
-    let qs = query.join('&')
-    if (method.toLowerCase() === 'get' && query.length > 0) {
-        url += (url.indexOf('?') < 0 ? '?' : '&') + qs
+function fetch (url = '', params = {}, method = 'get', contentType = 'form', insurance, timeout = 15000) {
+  contentType === 'form' && (contentType = 'application/x-www-form-urlencoded')
+  contentType === 'json' && (contentType = 'application/json')
+  contentType === 'file' && (contentType = 'multipart/form-data')
+  const query = []
+  for (const k in params) {
+    query.push(k + '=' + params[k])
+  }
+  let qs = query.join('&')
+  if (method.toLowerCase() === 'get' && query.length > 0) {
+    url += (url.indexOf('?') < 0 ? '?' : '&') + qs
+  }
+  if (contentType !== 'application/x-www-form-urlencoded' && method !== 'get') {
+    qs = params
+  }
+  return new Promise((resolve, reject) => {
+    const requestParams = {
+      timeout,
+      method,
+      url: '/api' + url,
+      data: qs,
+      headers: {
+        'Content-Type': contentType
+      }
     }
-    if (contentType !== 'application/x-www-form-urlencoded' && method !== 'get') {
-        qs = params
+    const success = (response) => {
+      const {
+        status,
+        data = {},
+        statusText
+      } = response
+      if (status >= 200 && status <= 401) {
+        if (data.code === 401) { // 未登录c
+          removeToken()
+          clean()
+          router.push(`/?redirect=${encodeURIComponent(window.location.href)}`)
+          reject(new Error('需要登录'))
+          Message.error('登录过期,请重新登录')
+          return
+        }
+        resolve(data)
+      } else if (status === 500) {
+        router.push('/500')
+      } else {
+        Message.success(status + '-' + statusText)
+      }
     }
-    return new Promise((resolve, reject) => {
-        let requestParams = {
-            timeout,
-            method: method,
-            url: '/api' + url,
-            data: qs,
-            headers: {
-                'Content-Type': contentType
-            }
+    axios(requestParams).then(success).catch((err) => {
+      if (/502|503|504/.test(err.message) || (err + '').indexOf('timeout') > -1) {
+        if (insurance) {
+          resolve(insurance)
+          return
         }
-        let success = (response) => {
-            let {
-                status,
-                data = {},
-                statusText
-            } = response
-            if (status >= 200 && status <= 401) {
-                if (data.code === 401) { // 未登录c
-                    removeToken()
-                    clean()
-                    router.push(`/?redirect=${encodeURIComponent(window.location.href)}`)
-                    reject(new Error('需要登录'))
-                    Message.error('登录过期,请重新登录')
-                    return
-                }
-                resolve(data)
-            } else if (status === 500) {
-                router.push('/500')
-            } else {
-                Message.success(status + '-' + statusText,)
-            }
+        let msg = '系统繁忙,正在为您排队中,请稍后再试'
+        if (window.location.href.indexOf('/zu') > -1) {
+          msg += ` ${err.message}`
         }
-        axios(requestParams).then(success).catch((err) => {
-            if (/502|503|504/.test(err.message) || (err + '').indexOf('timeout') > -1) {
-                if (insurance) {
-                    resolve(insurance)
-                    return
-                }
-                let msg = '系统繁忙,正在为您排队中,请稍后再试'
-                if (window.location.href.indexOf('/zu') > -1) {
-                    msg += ` ${err.message}`
-                }
-                Message.error(msg)
-            } else {
-                Message.error(err.response.data && err.response.data.msg ? err.response.data.msg : '网络异常,请点击重试')
-            }
-        })
+        Message.error(msg)
+      } else {
+        Message.error(err.response.data && err.response.data.msg ? err.response.data.msg : '网络异常,请点击重试')
+      }
     })
+  })
 }
 
 export default fetch

+ 4 - 4
src/layout/index.vue

@@ -3,11 +3,11 @@
     <el-aside width="200px" >
       <left/>
     </el-aside>
-    <el-container >
-      <el-header style='padding: 0'>
-        <top/>
+    <el-container>
+      <el-header style='padding: 0' class='light-green-bg full-width'>
+          <top class='full-width'/>
       </el-header>
-      <el-main >
+      <el-main>
         <el-card >
           <keep-alive v-if='$route.meta.keepAlive'>
             <router-view class="avue-view"/>

+ 28 - 14
src/layout/top.vue

@@ -1,27 +1,41 @@
 <template>
-    <div class='flex flex-align-center full-width top padding-left padding-right top'>
-      <el-icon :size="20">
-        <Filter />
-      </el-icon>
-      <el-breadcrumb class='ml-20' separator="/">
-        <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
-        <el-breadcrumb-item
-        ><a href="/">promotion management</a></el-breadcrumb-item
-        >
-        <el-breadcrumb-item>promotion list</el-breadcrumb-item>
-        <el-breadcrumb-item>promotion detail</el-breadcrumb-item>
-      </el-breadcrumb>
-    </div>
+      <div class='flex flex-align-center flex-justify-between top flex-child-grow'>
+        <div class='flex flex-justify-start flex-child-average  padding-left padding-right '>
+          <el-icon :size="20">
+            <Filter />
+          </el-icon>
+          <el-breadcrumb class='ml-20' separator="/">
+            <el-breadcrumb-item v-for='item in nav.menus' :key='item.id'>
+              <a :href="item.path">{{ item.name }}</a>
+            </el-breadcrumb-item>
+          </el-breadcrumb>
+        </div>
+        <div class='flex-child-average flex-justify-end flex padding-right  '>
+          <el-button @click='nav.cleanMenu()'>清除缓存</el-button>
+        </div>
+      </div>
 </template>
 
 <script>
+import navStore from '../store/nav.js'
+
 export default {
-  name: 'top'
+  name: 'top',
+  setup () {
+    const nav = navStore()
+    return { nav }
+  },
+  created () {
+    this.nav.$subscribe((res) => {
+      console.log(res.events.target)
+    })
+  }
 }
 </script>
 
 <style lang='scss' scoped>
 .top{
+  width: 92.5%;
   height: 60px;
   z-index: 1;
   background-color: white;

+ 6 - 1
src/main.js

@@ -5,6 +5,7 @@ import App from './App.vue'
 import router from './router/index.js'
 import api from './api/index.js'
 import { createPinia } from 'pinia'
+import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
 import * as wps from './static/web-office-sdk-v1.1.19.es.js'
 import elementPlus from 'element-plus'
 import * as ElementPlusIconsVue from '@element-plus/icons-vue'
@@ -15,12 +16,16 @@ const myApp = createApp(App)
 myApp.config.globalProperties.$router = router
 myApp.config.globalProperties.$api = api
 myApp.config.globalProperties.$wps = wps
+myApp.config.devtools = true
+
+/** 开启Pinia 持久化插件 需要在store 中进行开启**/
 const pinia = createPinia()
+pinia.use(piniaPluginPersistedstate)
 for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
   myApp.component(key, component)
 }
 myApp
-  .use(router)
   .use(pinia)
+  .use(router)
   .use(elementPlus, { size: 'small', zIndex: 300 })
   .mount('#app')

+ 15 - 0
src/page/404.vue

@@ -0,0 +1,15 @@
+<template>
+  <div class='full-width full-height flex flex-center'>
+    <el-empty description='404'/>
+  </div>
+</template>
+
+<script>
+export default {
+  name: '404'
+}
+</script>
+
+<style scoped>
+
+</style>

+ 58 - 4
src/router/index.js

@@ -1,9 +1,28 @@
-import { createRouter } from 'vue-router'
+import { createRouter, onBeforeRouteLeave } from 'vue-router'
 import * as vueRouter from 'vue-router'
 import Layout from '../layout/index.vue'
+import navStore from '../store/nav.js'
 
 // 路由信息
 const routes = [
+  /**
+   * page 路由
+   */
+  {
+    path: '/error',
+    name: '404',
+    component: Layout,
+    children: [
+      {
+        path: '404',
+        name: '404',
+        component: () => import('../page/404.vue')
+      }
+    ]
+  },
+  /**
+   * view 页面路由
+   */
   {
     path: '/',
     name: '首页',
@@ -15,11 +34,40 @@ const routes = [
         component: () => import('../views/home/index.vue')
       },
       {
-        path: '/setting',
+        path: 'setting',
         name: '设置',
         component: () => import('../views/setting/index.vue')
       }
     ]
+  },
+  {
+    path: '/user',
+    name: '个人中心',
+    component: Layout,
+    children: [
+      {
+        path: 'index',
+        name: '个人中心',
+        component: () => import('../views/user/index.vue')
+      },
+      {
+        path: 'pass',
+        name: '修改密码',
+        component: () => import('../views/user/pass.vue')
+      }
+    ]
+  },
+  {
+    path: '/system',
+    name: '系统设置',
+    component: Layout,
+    children: [
+      {
+        path: 'index',
+        name: '系统设置',
+        component: () => import('../views/system/index.vue')
+      }
+    ]
   }
 ]
 
@@ -30,8 +78,14 @@ const router = createRouter({
 })
 
 router.beforeEach((to, from, next) => {
-  console.log(from)
-  next()
+  const nav = navStore()
+  nav.updateMenu(to)
+  if (to.matched.length) {
+    next()
+  } else {
+    next('/error/404')
+    console.log(to)
+  }
 })
 
 export default router

+ 29 - 0
src/store/nav.js

@@ -0,0 +1,29 @@
+import { defineStore } from 'pinia'
+
+export const navStore = defineStore('navStore', {
+  /** 持久化 **/
+  persist: true,
+  state: () => ({ menus: [] }),
+  actions: {
+    /**
+     * 添加浏览记录菜单
+     * @param menu
+     */
+    updateMenu (menu) {
+      const index = this.menus.findIndex(m => m.path === menu.path)
+      if (index === -1) {
+        this.menus.push(menu)
+      } else {
+        this.menus.splice(index + 1, this.menus.length - index - 1)
+      }
+    },
+    /**
+     * 清空浏览记录菜单(用户退出时候,必须调调用此菜单)
+     */
+    cleanMenu () {
+      this.menus = []
+    }
+  }
+})
+
+export default navStore

+ 5 - 3
src/views/setting/index.vue

@@ -1,10 +1,10 @@
 <template>
   <div class='full-width full-height flex flex-col flex-justify-start'>
     <div>
-      <el-button>设置</el-button>
+      <el-button @click='push'>设置</el-button>
     </div>
     <div v-for='item in list' :key='item.id' class='mt-20'>
-      <button>{{item.title}}</button>
+      <button >{{item.title}}</button>
     </div>
   </div>
 </template>
@@ -31,12 +31,14 @@ export default {
       console.log(this.user.info)
       this.user.info = { user: '123', name: 'holle' }
       this.user.$dispose()
-      console.log(this.user.info.name)
       this.$api.loginApi.sendSMS({ current: 1, size: 200 }).then((res) => {
         if (res.code === 200) {
           this.list = res.data.records
         }
       })
+    },
+    push () {
+      this.$router.push({ path: '/user/index', query: { id: 12, type: 'test' } })
     }
   }
 }

+ 15 - 0
src/views/system/index.vue

@@ -0,0 +1,15 @@
+<template>
+  <div>
+    System
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'index'
+}
+</script>
+
+<style scoped>
+
+</style>

+ 15 - 0
src/views/user/index.vue

@@ -0,0 +1,15 @@
+<template>
+  <div>
+    <router-link to='/user/pass'><el-button >调整到404</el-button></router-link>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'index.vue'
+}
+</script>
+
+<style scoped>
+
+</style>

+ 15 - 0
src/views/user/pass.vue

@@ -0,0 +1,15 @@
+<template>
+  <div>
+    <el-tag>修改PASS</el-tag>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'pass'
+}
+</script>
+
+<style scoped>
+
+</style>

+ 5 - 0
yarn.lock

@@ -1472,6 +1472,11 @@ picomatch@^2.0.4, picomatch@^2.2.1:
   resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
   integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
 
+pinia-plugin-persistedstate@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-2.1.1.tgz#584c416cdc278689ae9d49483621ec96dcb7d6ef"
+  integrity sha512-HUgsU5IRtM75eAQiIqzT3p1oPEuYH1/B2ipTMU++yE+FV0LkHaBswdKXs0RMWYCmugO8s62oxLTh/N1dLNp+5A==
+
 pinia@^2.0.16:
   version "2.0.16"
   resolved "https://registry.yarnpkg.com/pinia/-/pinia-2.0.16.tgz#0105db595f5f792e17c04692e36807d8ea62f5cc"