408249787@qq.com 1 週間 前
コミット
87c6e577ed

+ 58 - 1
src/components/MultiTab/MultiTab.vue

@@ -37,18 +37,28 @@ export default {
     this.pages.push(this.$route)
     this.fullPathList.push(this.$route.fullPath)
     this.selectedLastPath()
+    // 初始化时将当前页面组件加入缓存
+    this.$nextTick(() => {
+      this.addCurrentToCache()
+    })
   },
   methods: {
     onEdit (targetKey, action) {
       this[action](targetKey)
     },
     remove (targetKey) {
+      const closedPage = this.pages.find(page => page.fullPath === targetKey)
       this.pages = this.pages.filter(page => page.fullPath !== targetKey)
       this.fullPathList = this.fullPathList.filter(path => path !== targetKey)
       // 判断当前标签是否关闭,若关闭则跳转到最后一个还存在的标签页
-      if (!this.fullPathList.includes(this.activeKey)) {
+      const needNavigate = !this.fullPathList.includes(this.activeKey)
+      if (needNavigate) {
         this.selectedLastPath()
       }
+      // 清理已关闭标签页的组件缓存
+      this.$nextTick(() => {
+        this.removePageFromCache(closedPage)
+      })
     },
     selectedLastPath () {
       this.activeKey = this.fullPathList[this.fullPathList.length - 1]
@@ -117,6 +127,49 @@ export default {
           <span style={{ userSelect: 'none' }}>{ title }</span>
         </a-dropdown>
       )
+    },
+    /**
+     * 解析路由对应的组件名称
+     * 优先从 $route.matched 获取已解析的组件 name,回退到路由 name
+     */
+    getRouteComponentName (route) {
+      if (!route) return null
+      const layoutComponents = ['BasicLayout', 'RouteView', 'PageView', 'UserLayout', 'BlankLayout']
+      // 从 matched 路由记录中获取组件名称
+      if (route.matched && route.matched.length > 0) {
+        const lastRecord = route.matched[route.matched.length - 1]
+        const component = lastRecord.components && lastRecord.components.default
+        if (component && component.name && !layoutComponents.includes(component.name)) {
+          return component.name
+        }
+      }
+      // 回退到路由名称
+      return route.name || null
+    },
+    /**
+     * 将当前路由组件加入缓存
+     */
+    addCurrentToCache () {
+      const name = this.getRouteComponentName(this.$route)
+      if (name) {
+        this.$store.dispatch('AddCachedView', name)
+      }
+    },
+    /**
+     * 关闭标签页时,从缓存中移除对应组件
+     * 仅当没有其他打开的标签使用同一组件时才移除
+     */
+    removePageFromCache (closedPage) {
+      if (!closedPage) return
+      const componentName = this.getRouteComponentName(closedPage)
+      if (!componentName) return
+      // 检查是否还有其他打开的标签页使用同一组件
+      const stillInUse = this.pages.some(page => {
+        return this.getRouteComponentName(page) === componentName
+      })
+      if (!stillInUse) {
+        this.$store.dispatch('DelCachedView', componentName)
+      }
     }
   },
   watch: {
@@ -126,6 +179,10 @@ export default {
         this.fullPathList.push(newVal.fullPath)
         this.pages.push(newVal)
       }
+      // 将当前页面组件加入缓存保活列表
+      this.$nextTick(() => {
+        this.addCurrentToCache()
+      })
     },
     activeKey: function (newPathKey) {
       this.$router.push({ path: newPathKey })

+ 1 - 1
src/config/defaultSettings.js

@@ -22,7 +22,7 @@ export default {
   fixSiderbar: false, // sticky siderbar
   autoHideHeader: false, //  auto hide header
   colorWeak: false,
-  multiTab: false,
+  multiTab: true,
   production: process.env.NODE_ENV === 'production' && process.env.VUE_APP_PREVIEW !== 'true',
   // vue-ls options
   storageOptions: {

+ 1 - 1
src/layouts/BasicLayout.vue

@@ -42,7 +42,7 @@
       <!-- layout content -->
       <a-layout-content :style="{ height: '100%', margin: '24px 24px 0', paddingTop: fixedHeader ? '64px' : '0' }">
         <multi-tab v-if="multiTab"></multi-tab>
-        <transition name="page-transition">
+        <transition name="page-transition" mode="out-in">
           <route-view />
         </transition>
       </a-layout-content>

+ 3 - 2
src/layouts/PageView.vue

@@ -41,7 +41,7 @@
       <div class="page-header-index-wide">
         <slot>
           <!-- keep-alive  -->
-          <keep-alive v-if="multiTab">
+          <keep-alive v-if="multiTab" :include="cachedViews">
             <router-view ref="content" />
           </keep-alive>
           <router-view v-else ref="content" />
@@ -90,7 +90,8 @@ export default {
   },
   computed: {
     ...mapState({
-      multiTab: state => state.app.multiTab
+      multiTab: state => state.app.multiTab,
+      cachedViews: state => state.app.cachedViews
     })
   },
   mounted () {

+ 35 - 18
src/layouts/RouteView.vue

@@ -8,28 +8,45 @@ export default {
     }
   },
   data () {
-    return {}
+    return {
+      cachedViews: []
+    }
+  },
+  computed: {
+    isMultiTab () {
+      return this.$store.getters.multiTab
+    }
+  },
+  watch: {
+    '$store.getters.cachedViews': {
+      handler (val) {
+        this.cachedViews = [...val]
+      },
+      immediate: true
+    }
   },
   render () {
     const { $route: { meta }, $store: { getters } } = this
-    const inKeep = (
-      <keep-alive>
-        <router-view />
-      </keep-alive>
-    )
-    const notKeep = (
-      <router-view />
-    )
-    // 这里增加了 multiTab 的判断,当开启了 multiTab 时
-    // 应当全部组件皆缓存,否则会导致切换页面后页面还原成原始状态
-    // 若确实不需要,可改为 return meta.keepAlive ? inKeep : notKeep
-    // if (!getters.multiTab && !meta.keepAlive) { // 原逻辑
-    //   return notKeep
-    // }
-    if (!meta.keepAlive) { // 不管是不是多页签模式,均不要缓存
-      return notKeep
+
+    // 多标签页模式:使用 keep-alive + include 缓存所有已打开的页面组件
+    if (getters.multiTab) {
+      return (
+        <keep-alive include={this.cachedViews}>
+          <router-view />
+        </keep-alive>
+      )
+    }
+
+    // 非多标签页模式:根据 meta.keepAlive 决定是否缓存
+    if (this.keepAlive || meta.keepAlive) {
+      return (
+        <keep-alive>
+          <router-view />
+        </keep-alive>
+      )
     }
-    return this.keepAlive || getters.multiTab || meta.keepAlive ? inKeep : notKeep
+
+    return <router-view />
   }
 }
 </script>

+ 1 - 0
src/store/getters.js

@@ -12,6 +12,7 @@ const getters = {
   permissions: state => state.user.permissions,
   addRouters: state => state.permission.addRouters,
   multiTab: state => state.app.multiTab,
+  cachedViews: state => state.app.cachedViews,
   lang: state => state.i18n.lang,
   purchaseType: state => state.purchase.type,
   addFlag: state => state.purchase.addFlag,

+ 26 - 1
src/store/modules/app.js

@@ -24,7 +24,9 @@ const app = {
     autoHideHeader: false,
     color: null,
     weak: false,
-    multiTab: true
+    multiTab: true,
+    // 多标签页保活:记录需要缓存的组件名称
+    cachedViews: []
   },
   mutations: {
     SET_SIDEBAR_TYPE: (state, type) => {
@@ -74,6 +76,20 @@ const app = {
     TOGGLE_MULTI_TAB: (state, bool) => {
       Vue.ls.set(DEFAULT_MULTI_TAB, bool)
       state.multiTab = bool
+    },
+    ADD_CACHED_VIEW: (state, name) => {
+      if (name && !state.cachedViews.includes(name)) {
+        state.cachedViews.push(name)
+      }
+    },
+    DEL_CACHED_VIEW: (state, name) => {
+      const index = state.cachedViews.indexOf(name)
+      if (index > -1) {
+        state.cachedViews.splice(index, 1)
+      }
+    },
+    CLEAR_CACHED_VIEW: (state) => {
+      state.cachedViews = []
     }
   },
   actions: {
@@ -115,6 +131,15 @@ const app = {
     },
     ToggleMultiTab ({ commit }, bool) {
       commit('TOGGLE_MULTI_TAB', bool)
+    },
+    AddCachedView ({ commit }, name) {
+      commit('ADD_CACHED_VIEW', name)
+    },
+    DelCachedView ({ commit }, name) {
+      commit('DEL_CACHED_VIEW', name)
+    },
+    ClearCachedView ({ commit }) {
+      commit('CLEAR_CACHED_VIEW')
     }
   }
 }

+ 1 - 1
src/views/repair/application-form/RepairOut.vue

@@ -21,7 +21,7 @@
 
       <div class="table-operator">
         <!--        <a-button v-if="$auth('repair-application-forms-add')" type="primary" icon="plus" @click="$refs.baseModal.base({},{filter: -1})">新增</a-button>-->
-        <a-button style="margin-left: 8px" v-if="$auth('repair-application-forms-add')" type="primary" icon="plus" @click="$refs.baseOutModal.base()">新增</a-button>
+        <!--       <a-button style="margin-left: 8px" v-if="$auth('repair-application-forms-add')" type="primary" icon="plus" @click="$refs.baseOutModal.base()">新增</a-button>-->
         <a-button style="margin-left: 8px" v-if="$auth('repair-application-forms-export')" type="primary" icon="download" @click="doExport">导出</a-button>
         <a-dropdown v-action:edit v-if="selectedRowKeys.length > 0 && $auth('repair-application-forms-del')">
           <a-menu slot="overlay">

+ 17 - 1
src/views/repair/application-form/modules/BaseOutForm.vue

@@ -12,6 +12,18 @@
       <a-form-item v-show="false" >
         <a-input v-decorator="['id']" type="hidden"/>
       </a-form-item>
+      <a-form-item v-show="false">
+        <a-input v-decorator="['sbId']" type="hidden"/>
+      </a-form-item>
+      <a-form-item v-show="false">
+        <a-input v-decorator="['sbNo']" type="hidden"/>
+      </a-form-item>
+      <a-form-item v-show="false">
+        <a-input v-decorator="['sbName']" type="hidden"/>
+      </a-form-item>
+      <a-form-item v-show="false">
+        <a-input v-decorator="['mainRepairId']" type="hidden"/>
+      </a-form-item>
 
       <row-list :col="2">
         <row-item>
@@ -123,13 +135,17 @@ export default {
     base (record, mainForm = {}) {
       this.visible = true
       // 如果是空标识添加
+      console.log(record, mainForm)
       const { form: { setFieldsValue } } = this
       if (this.BaseTool.Object.isBlank(record)) {
         this.modalTitle = '添加'
         if (mainForm != null && mainForm.id != null) {
           this.$nextTick(() => {
             setFieldsValue({
-              id: mainForm.id
+              sbId: mainForm.sbId,
+              sbNo: mainForm.sbNo,
+              sbName: mainForm.sbName,
+              mainRepairId: mainForm.id
             })
           })
         }

+ 1 - 1
src/views/repair/application-form/modules/DetailRepair.vue

@@ -186,7 +186,7 @@
 
     </a-card>
     <check-form ref="checkForm" @ok="handleOk" />
-    <base-out-form ref="outForm" @ok="handleCancel" />
+    <base-out-form ref="outForm" @ok="handleOk" />
     <finish-form ref="finishForm" @ok="handleOk" />
     <dispatch-form ref="dispatchForm" @ok="handleCancel" />
     <assign-form ref="assignForm" @ok="handleCancel" />