feat: 页面缓存

This commit is contained in:
zhangyh
2025-10-21 11:21:15 +08:00
parent d25881d103
commit f5788b7235
10 changed files with 976 additions and 116 deletions

View File

@@ -27,5 +27,6 @@ rules: {
], ],
parserOptions: { parserOptions: {
ecmaVersion: 'latest' ecmaVersion: 'latest'
} },
globals: { defineOptions: 'readonly' }
} }

966
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -44,6 +44,7 @@
"typescript": "~4.8.4", "typescript": "~4.8.4",
"unplugin-auto-import": "^0.15.3", "unplugin-auto-import": "^0.15.3",
"unplugin-vue-components": "^0.24.1", "unplugin-vue-components": "^0.24.1",
"unplugin-vue-define-options": "^3.1.1",
"vite": "^4.1.4", "vite": "^4.1.4",
"vite-plugin-svg-icons": "^2.0.1", "vite-plugin-svg-icons": "^2.0.1",
"vue-tsc": "^1.2.0" "vue-tsc": "^1.2.0"

View File

@@ -1,7 +1,11 @@
<template> <template>
<RouterView /> <RouteCache />
</template> </template>
<script setup lang="ts">
import RouteCache from '@/components/RouteCache.vue'
</script>
<style lang="less"> <style lang="less">
#app{ #app{

View File

@@ -0,0 +1,60 @@
<template>
<router-view v-slot="{ Component, route }">
<keep-alive :include="cachedViews">
<component :is="Component" :key="route.name" />
</keep-alive>
</router-view>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
// 缓存的组件名称列表
const cachedViews = ref<string[]>([])
// 监听路由变化,管理缓存
watch(
() => route,
(newRoute) => {
const routeName = newRoute.name as string
const shouldCache = newRoute.meta?.cache === true
console.log('🔄 路由变化:', { routeName, shouldCache, currentCache: cachedViews.value })
if (shouldCache && routeName && !cachedViews.value.includes(routeName)) {
// 添加到缓存列表
cachedViews.value.push(routeName)
console.log('✅ 添加到缓存:', routeName)
} else if (!shouldCache && routeName && cachedViews.value.includes(routeName)) {
// 从缓存列表中移除
const index = cachedViews.value.indexOf(routeName)
if (index > -1) {
cachedViews.value.splice(index, 1)
console.log('❌ 从缓存移除:', routeName)
}
}
},
{ immediate: true, deep: true }
)
// 提供清除缓存的方法
const clearCache = (routeName?: string) => {
if (routeName) {
const index = cachedViews.value.indexOf(routeName)
if (index > -1) {
cachedViews.value.splice(index, 1)
}
} else {
cachedViews.value = []
}
}
// 暴露方法供外部使用
defineExpose({
clearCache,
cachedViews
})
</script>

View File

@@ -53,7 +53,8 @@ const router = createRouter({
{ {
path: '/asistant', path: '/asistant',
name: 'asistant', name: 'asistant',
component: () => import('../views/asistant/index.vue') component: () => import('../views/asistant/index.vue'),
meta: { cache: true }
}, },
{ {
path: '/workshop', path: '/workshop',
@@ -62,7 +63,7 @@ const router = createRouter({
children: [ children: [
{ {
path: '/workshop', path: '/workshop',
redirect: "/workshop/selectStyle", redirect: '/workshop/selectStyle'
}, },
{ {
path: '/workshop/selectStyle', path: '/workshop/selectStyle',
@@ -95,19 +96,19 @@ const router = createRouter({
// 自定义创作 // 自定义创作
path: '/workshop/customize', path: '/workshop/customize',
name: 'customize', name: 'customize',
component: () => import('../views/Workshop/customize.vue'), component: () => import('../views/Workshop/customize.vue')
}, },
{ {
// library // library
path: '/workshop/library', path: '/workshop/library',
name: 'library', name: 'library',
component: () => import('../views/Workshop/library.vue'), component: () => import('../views/Workshop/library.vue')
}, },
{ {
// creation // creation
path: '/workshop/creation', path: '/workshop/creation',
name: 'creation', name: 'creation',
component: () => import('../views/Workshop/creation/index.vue'), component: () => import('../views/Workshop/creation/index.vue')
}, },
{ {
// 完成创建 // 完成创建

5
src/types/define-options.d.ts vendored Normal file
View File

@@ -0,0 +1,5 @@
declare global {
const defineOptions: <T = Record<string, any>>(options: T) => T
}
export {}

View File

@@ -24,10 +24,14 @@ import HeaderTitle from '@/components/HeaderTitle.vue'
import NoticeList from './components/NoticeList.vue' import NoticeList from './components/NoticeList.vue'
import InputArea from './components/InputArea.vue' import InputArea from './components/InputArea.vue'
import GenerateLoading from './components/GenerateLoading.vue' import GenerateLoading from './components/GenerateLoading.vue'
import { ref, onMounted } from 'vue' import { ref, onMounted, onActivated } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
const router = useRouter() const router = useRouter()
defineOptions({
name:'asistant'
})
// 定义NoticeList组件引用类型 // 定义NoticeList组件引用类型
interface NoticeListRef { interface NoticeListRef {
simulateSendMessage: () => void simulateSendMessage: () => void
@@ -77,9 +81,15 @@ const messageList = ref<ChatMessage[]>([
]) ])
onMounted(() => { onMounted(() => {
console.log('🚀 组件挂载 - onMounted 触发')
// handleSendMessage('123') // handleSendMessage('123')
}) })
onActivated(() => {
console.log('🔄 缓存页面激活 - onActivated 触发')
console.log('当前消息数量:', messageList.value.length)
})
const handleSendMessage = (message: string): void => { const handleSendMessage = (message: string): void => {
console.log('收到消息:', message) console.log('收到消息:', message)
messageList.value.push({ messageList.value.push({
@@ -98,7 +108,7 @@ const handleContinue = () => {
isLoading.value = true isLoading.value = true
setTimeout(() => { setTimeout(() => {
router.push('/workshop/selectStyle') router.push('/workshop/selectStyle')
// isLoading.value = false isLoading.value = false
}, 1000) }, 1000)
} }
</script> </script>

View File

@@ -1,11 +1,11 @@
{ {
"extends": "@vue/tsconfig/tsconfig.web.json", "extends": "@vue/tsconfig/tsconfig.web.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"], "include": ["env.d.ts", "src/**/*", "src/**/*.vue", "src/types/**/*.d.ts"],
"compilerOptions": { "compilerOptions": {
"forceConsistentCasingInFileNames": false, // ⚠️ 禁用大小写检查 "forceConsistentCasingInFileNames": false, // ⚠️ 禁用大小写检查
"allowJs": true, "allowJs": true,
"baseUrl": ".", "baseUrl": ".",
"types": ["node"], "types": ["node", "unplugin-vue-define-options/macros-global"],
"paths": { "paths": {
"@/*": ["./src/*"], "@/*": ["./src/*"],
"_c/*": ["./src/components/*"] "_c/*": ["./src/components/*"]

View File

@@ -4,6 +4,7 @@ import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite' import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite' import Components from 'unplugin-vue-components/vite'
import DefineOptions from 'unplugin-vue-define-options/vite'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons' import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path' import path from 'path'
import { VantResolver } from '@vant/auto-import-resolver' import { VantResolver } from '@vant/auto-import-resolver'
@@ -16,6 +17,7 @@ import { VantResolver } from '@vant/auto-import-resolver'
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
vue(), vue(),
DefineOptions(),
// ... // ...
AutoImport({ AutoImport({
resolvers: [VantResolver()], resolvers: [VantResolver()],