diff --git a/src/modules/page9/IndexPage.vue b/src/modules/page9/IndexPage.vue
index a9cc79903f80fdb6e5845c47f43a1d15b7f8833f..0ac57a228d88e7628441f795b5ca885e17907f4c 100644
--- a/src/modules/page9/IndexPage.vue
+++ b/src/modules/page9/IndexPage.vue
@@ -2,6 +2,11 @@
  * 动画2
  * https://www.youtube.com/@OnlineTutorialsYT/playlists
   -->
+<script lang="ts">
+export default {
+  name: 'PAGE9',
+};
+</script>
 <script setup lang="ts">
 import { ref } from 'vue';
 import TextVue from './element/TextVue.vue';
@@ -10,7 +15,8 @@ import SvgLineDrawingAnimation from './element/SvgLineDrawingAnimation.vue';
 import FlyingTextAnimationEffects from './element/FlyingTextAnimationEffects.vue';
 import TransformationAnimation from './element/TransformationAnimation.vue';
 import AgGridStudy from './element/AgGridStudy2.vue';
-import AgGridGroup1 from './element/AgGridGroup1.vue';
+import AgGridMaster from './element/AgGridMaster.vue';
+import AgGridDetailGrids from './element/AgGridDetailGrids.vue';
 
 const listData = [
   {
@@ -38,13 +44,17 @@ const listData = [
     name: 'ag-grid-study',
   },
   {
-    title: 'AG grid 分组1',
-    name: 'ag-grid-group1',
+    title: 'AG grid 细节表格',
+    name: 'ag-grid-master',
+  },
+  {
+    title: 'Vue Data Grid: Master / Detail - Detail Grids',
+    name: 'ag-grid-detail-grids',
   },
 ];
 const isShow = ref(true);
-const elementName = ref('ag-grid-group1');
-const elementTitle = ref('AG grid 分组1');
+const elementName = ref('ag-grid-detail-grids');
+const elementTitle = ref('Vue Data Grid: Master / Detail - Detail Grids');
 
 function onclick(data: any) {
   elementTitle.value = data.title;
@@ -55,6 +65,7 @@ function goBack() {
   isShow.value = false;
 }
 </script>
+
 <template>
   <div>
     <div v-if="isShow" class="main">
@@ -82,7 +93,8 @@ function goBack() {
           v-if="elementName === 'transformation-animation'"
         />
         <ag-grid-study v-if="elementName === 'ag-grid-study'" />
-        <ag-grid-group1 v-if="elementName === 'ag-grid-group1'" />
+        <ag-grid-master v-if="elementName === 'ag-grid-master'" />
+        <ag-grid-detail-grids v-if="elementName === 'ag-grid-detail-grids'" />
       </div>
     </div>
     <div v-else>
diff --git a/src/modules/page9/element/AgGridDetailGrids.vue b/src/modules/page9/element/AgGridDetailGrids.vue
new file mode 100644
index 0000000000000000000000000000000000000000..1c5815eefe6c461de0121d7e5e37a73de1632ec0
--- /dev/null
+++ b/src/modules/page9/element/AgGridDetailGrids.vue
@@ -0,0 +1,113 @@
+<!--
+ * AG-grid 细节网格细节配置
+ * https://www.ag-grid.com/vue-data-grid/master-detail-grids/
+ -->
+<script setup lang="ts">
+import { ref, reactive, onMounted } from 'vue';
+import { AgGridVue } from 'ag-grid-vue3';
+import 'ag-grid-enterprise';
+import 'ag-grid-community/styles/ag-grid.css';
+import 'ag-grid-community/styles/ag-theme-alpine.css';
+
+const defaultColDef = {
+  flex: 1,
+  suppressMenu: true, // 禁用标题行菜单
+};
+
+const gridApi = ref<any>(null);
+const gridColumnApi = ref<any>(null);
+const detailCellRendererParams = reactive({
+  // 提供要在细节网格上使用的网格选项
+  detailGridOptions: {
+    columnDefs: [
+      { field: 'callId', headerName: '呼叫标识' },
+      { field: 'direction', headerName: '方向' },
+      { field: 'number', headerName: '号码' },
+      {
+        field: 'duration',
+        headerName: '持续时间',
+        valueFormatter: 'x.toLocaleString() + "ç§’"',
+      },
+      { field: 'switchCode', headerName: '开关代码' },
+    ],
+    defaultColDef,
+    rowSelection: 'multiple',
+    suppressRowClickSelection: true, // 抑制行点击选择
+    enableRangeSelection: true, // 启用范围选择
+    pagination: true,
+    paginationAutoPageSize: true,
+  },
+  // 获得每个细节网格的行数
+  getDetailRowData: (params: any) => {
+    params.successCallback(params.data.callRecords || []);
+  },
+});
+
+const state = reactive({
+  columnDefs: [
+    { field: 'name', headerName: '姓名', cellRenderer: 'agGroupCellRenderer' },
+    { field: 'account', headerName: '帐户' },
+    { field: 'calls', headerName: '呼叫' },
+    {
+      field: 'minutes',
+      headerName: '分钟',
+      valueFormatter: 'x.toLocaleString() + "分钟"',
+    },
+  ],
+  rowData: [] as any,
+});
+
+onMounted(() => {
+  fetch('https://www.ag-grid.com/example-assets/master-detail-data.json')
+    .then((result) => result.json())
+    .then((remoteRowData) => {
+      state.rowData = remoteRowData;
+      console.log('rowData', state.rowData[0]);
+    });
+
+  // .then((remoteRowData) => (state.rowData = remoteRowData));
+});
+
+function onGridReady(params: any) {
+  gridApi.value = params.api;
+  gridColumnApi.value = params.columnApi;
+}
+
+function isRowMaster(dataItem: any) {
+  let flag;
+  if (dataItem && dataItem.callRecords && dataItem.callRecords.length > 0) {
+    flag = true;
+  } else {
+    flag = false;
+  }
+  return flag;
+}
+</script>
+<template>
+  <div class="box">
+    <!-- 
+        rowSelection="multiple":多选,按住control键多选;【control+shift+鼠标点击】可选中多行
+        animateRows=true:启用行动画
+        :masterDetail="true" 启用展开的细节网格行
+        :isRowMaster="isRowMaster" 确定哪一个行该展开
+     -->
+
+    <div>
+      <ag-grid-vue
+        style="height: 700px"
+        class="ag-theme-alpine"
+        :columnDefs="state.columnDefs"
+        :rowData="state.rowData"
+        :defaultColDef="defaultColDef"
+        :animateRows="true"
+        :masterDetail="true"
+        :isRowMaster="isRowMaster"
+        :detailCellRendererParams="detailCellRendererParams"
+        @grid-ready="onGridReady"
+      >
+      </ag-grid-vue>
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped></style>
diff --git a/src/modules/page9/element/AgGridGroup1.vue b/src/modules/page9/element/AgGridMaster.vue
similarity index 100%
rename from src/modules/page9/element/AgGridGroup1.vue
rename to src/modules/page9/element/AgGridMaster.vue
diff --git a/src/router/routes.ts b/src/router/routes.ts
index 91ced5c2d5dbfb690a62225445637bf907e7c7e8..8d80c1b3d3df500f05004454ed21594673cbffb6 100644
--- a/src/router/routes.ts
+++ b/src/router/routes.ts
@@ -10,7 +10,7 @@ const routes: RouteRecordRaw[] = [
         path: '',
         name: 'LaoutIndexPage',
         component: () => import('pages/IndexPage.vue'),
-        redirect: '/page10',
+        redirect: '/page9',
         children: [
           {
             path: 'page1',