diff --git a/docs/.vitepress/components.ts b/docs/.vitepress/components.ts
index b8944bd..aaedf4c 100644
--- a/docs/.vitepress/components.ts
+++ b/docs/.vitepress/components.ts
@@ -36,6 +36,13 @@ export interface ComponentMeta {
export const COMPONENT_LIST: ComponentMeta[] = [
// ---------- 布局组件 ----------
+ {
+ name: "PageTransition",
+ title: "PageTransition 页面过渡",
+ description: "为 Vue Router 页面提供可配置的层级滑动过渡与按路由缓存能力。",
+ category: "布局组件",
+ entry: "src/components/page-transition/index.vue"
+ },
{
name: "RootLayout",
title: "RootLayout 根布局",
diff --git a/docs/components/index.md b/docs/components/index.md
index 527e76c..86222f6 100644
--- a/docs/components/index.md
+++ b/docs/components/index.md
@@ -1,11 +1,12 @@
# 组件总览
-共 15 个组件,分为布局、编辑器、交互与 AI 对话四类。
+共 16 个组件,分为布局、编辑器、交互与 AI 对话四类。
## 布局组件
| 组件 | 说明 |
| --- | --- |
+| [PageTransition](/components/page-transition) | 为 Vue Router 页面提供可配置的层级滑动过渡与按路由缓存能力。 |
| [RootLayout](/components/root-layout) | 移动端页面骨架,主体内容之外自动渲染版权与备案信息。 |
| [Space](/components/space) | 控制子元素之间的间距与排列方向,支持分隔符。 |
diff --git a/docs/components/page-transition.md b/docs/components/page-transition.md
new file mode 100644
index 0000000..d2c4cb7
--- /dev/null
+++ b/docs/components/page-transition.md
@@ -0,0 +1,37 @@
+# PageTransition 页面过渡
+
+为 Vue Router 页面提供可配置的页面过渡和按路由缓存能力。
+
+## 基础用法
+
+`PageTransition` 必须放在 `RouterView` 所在的路由布局中,并且自身需要有明确的宽高。
+
+```vue
+
+
+
+
+
+```
+
+组件默认根据路由层级选择 `push-left` 和 `push-right`。层级的解析顺序是:`transitionDepth` query、`depth` meta、动态层级 meta,最后回退到 `matched.length`。业务路由结构特殊时,直接传入 `get-route-depth`,不要让组件猜测业务规则。
+
+## 缓存页面
+
+`keep-alive` 支持布尔值或路由谓词。谓词返回 `true` 的页面会进入缓存,`keep-alive-max` 用于限制缓存数量。默认不缓存页面,避免通用布局意外保留业务表单状态。
+
+## 自定义过渡
+
+`transition` 默认值为 `auto`,也可以传入 `false` 禁用过渡、传入字符串使用自定义过渡名,或传入函数按目标路由和来源路由返回过渡名。组件内置 `push-left`、`push-right` 和 `fade`。
+
+组件默认尊重系统的“减少动态效果”设置;如果业务必须保持页面翻页动画,可以设置 `:respect-reduced-motion="false"`。
+
+## API
+
+
diff --git a/src/components/index.ts b/src/components/index.ts
index 9d34599..e1daeef 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -1,5 +1,6 @@
/** 导出所有组件 */
import RootLayout from "./root-layout";
+import PageTransition from "./page-transition";
import DurationPicker from "./duration-picker";
import CodeEditor from "./code-editor";
import TiptapEditor from "./tiptap-editor";
@@ -19,6 +20,7 @@ import {
export default [
RootLayout,
+ PageTransition,
DurationPicker,
CodeEditor,
TiptapEditor,
@@ -37,6 +39,7 @@ export default [
export {
RootLayout,
+ PageTransition,
DurationPicker,
CodeEditor,
TiptapEditor,
@@ -88,6 +91,17 @@ export type {
SpaceSlots
} from "./space";
+export type {
+ PageTransitionBackground,
+ PageTransitionClass,
+ PageTransitionKeepAliveMatcher,
+ PageTransitionNameResolver,
+ PageTransitionProps,
+ PageTransitionRoute,
+ PageTransitionRouteDepthResolver,
+ PageTransitionRouteKeyResolver
+} from "./page-transition";
+
export type {
CodeEditorExpose
} from "./code-editor";
diff --git a/src/components/page-transition/index.ts b/src/components/page-transition/index.ts
new file mode 100644
index 0000000..1b4a1d5
--- /dev/null
+++ b/src/components/page-transition/index.ts
@@ -0,0 +1,16 @@
+import view from "./index.vue";
+import { WebToolkit } from "timi-web";
+
+export type {
+ PageTransitionBackground,
+ PageTransitionClass,
+ PageTransitionKeepAliveMatcher,
+ PageTransitionNameResolver,
+ PageTransitionProps,
+ PageTransitionRoute,
+ PageTransitionRouteDepthResolver,
+ PageTransitionRouteKeyResolver
+} from "./type";
+
+export const PageTransition = WebToolkit.withInstall(view);
+export default PageTransition;
diff --git a/src/components/page-transition/index.vue b/src/components/page-transition/index.vue
new file mode 100644
index 0000000..58d3773
--- /dev/null
+++ b/src/components/page-transition/index.vue
@@ -0,0 +1,333 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/page-transition/type.ts b/src/components/page-transition/type.ts
new file mode 100644
index 0000000..68613c3
--- /dev/null
+++ b/src/components/page-transition/type.ts
@@ -0,0 +1,61 @@
+import type { StyleValue } from "vue";
+import type { RouteLocationNormalized, RouteLocationNormalizedLoaded } from "vue-router";
+
+/** PageTransition 可接收的路由对象。 */
+export type PageTransitionRoute = RouteLocationNormalized | RouteLocationNormalizedLoaded;
+
+/** 根据路由计算页面层级,用于决定前进或后退动画。 */
+export type PageTransitionRouteDepthResolver = (route: PageTransitionRoute) => number | undefined;
+
+/** 根据路由生成页面 key。 */
+export type PageTransitionRouteKeyResolver = (route: PageTransitionRoute) => PropertyKey;
+
+/** 决定当前路由是否进入 keep-alive。 */
+export type PageTransitionKeepAliveMatcher = boolean | ((route: PageTransitionRoute) => boolean);
+
+/** 自定义过渡名称;返回 false 或传入 false 时不使用过渡。 */
+export type PageTransitionNameResolver =
+ | "auto"
+ | string
+ | false
+ | ((to: PageTransitionRoute, from: PageTransitionRoute) => string | false);
+
+/** 页面容器 class 的类型。 */
+export type PageTransitionClass = string | string[] | Record;
+
+/** 页面容器的背景色,可以按路由动态计算。 */
+export type PageTransitionBackground = string | ((route: PageTransitionRoute) => string | undefined);
+
+/** PageTransition 的公开属性。 */
+export interface PageTransitionProps {
+ /** 过渡名称;auto 会根据路由层级使用 push-left / push-right。 */
+ transition?: PageTransitionNameResolver;
+ /** Vue Transition 的模式。 */
+ transitionMode?: "out-in" | "in-out";
+ /** 是否在首次渲染时播放过渡。 */
+ appear?: boolean;
+ /** 是否尊重系统的减少动态效果设置,默认开启。 */
+ respectReducedMotion?: boolean;
+ /** 是否缓存页面,也可以按路由决定。默认不缓存。 */
+ keepAlive?: PageTransitionKeepAliveMatcher;
+ /** keep-alive 最多保留的页面数量。 */
+ keepAliveMax?: number;
+ /** 自定义路由层级解析器。 */
+ getRouteDepth?: PageTransitionRouteDepthResolver;
+ /** 路由 query 中的层级字段名,默认是 transitionDepth。 */
+ routeDepthQueryKey?: string;
+ /** 路由 meta 中的固定层级字段名,默认是 depth。 */
+ routeDepthMetaKey?: string;
+ /** 动态层级的起始层级字段名,默认是 baseDepth。 */
+ routeDepthBaseMetaKey?: string;
+ /** 标记动态层级的 meta 字段名,默认是 dynamicDepth。 */
+ routeDepthDynamicMetaKey?: string;
+ /** 自定义路由 key,默认使用 path,避免普通 query 变化重建页面。 */
+ getRouteKey?: PageTransitionRouteKeyResolver;
+ /** 页面容器的背景色,默认使用 TDesign 页面背景变量。 */
+ pageBackground?: PageTransitionBackground;
+ /** 页面容器 class。 */
+ pageClass?: PageTransitionClass;
+ /** 页面容器 style。 */
+ pageStyle?: StyleValue;
+}