diff --git a/apps/web-antd/src/components/description/index.ts b/apps/web-antd/src/components/description/index.ts
new file mode 100644
index 00000000..17a80cf6
--- /dev/null
+++ b/apps/web-antd/src/components/description/index.ts
@@ -0,0 +1,7 @@
+import { withInstall } from '#/utils';
+
+import description from './src/description.vue';
+
+export * from './src/typing';
+export { useDescription } from './src/useDescription';
+export const Description = withInstall(description);
diff --git a/apps/web-antd/src/components/description/src/description.vue b/apps/web-antd/src/components/description/src/description.vue
new file mode 100644
index 00000000..e2850691
--- /dev/null
+++ b/apps/web-antd/src/components/description/src/description.vue
@@ -0,0 +1,210 @@
+
diff --git a/apps/web-antd/src/components/description/src/typing.ts b/apps/web-antd/src/components/description/src/typing.ts
new file mode 100644
index 00000000..41703704
--- /dev/null
+++ b/apps/web-antd/src/components/description/src/typing.ts
@@ -0,0 +1,47 @@
+import type { Recordable } from '@vben/types';
+import type { DescriptionsProps } from 'ant-design-vue/es/descriptions';
+import type { JSX } from 'vue/jsx-runtime';
+
+import type { CSSProperties, VNode } from 'vue';
+
+export interface DescItem {
+ labelMinWidth?: number;
+ contentMinWidth?: number;
+ labelStyle?: CSSProperties;
+ field: string;
+ label: JSX.Element | string | VNode;
+ // Merge column
+ span?: number;
+ show?: (...arg: any) => boolean;
+ // render
+ render?: (
+ val: any,
+ data: Recordable,
+ ) => Element | JSX.Element | number | string | undefined | VNode;
+}
+
+export interface DescriptionProps extends DescriptionsProps {
+ // Whether to include the collapse component
+ useCollapse?: boolean;
+ /**
+ * item configuration
+ * @type DescItem
+ */
+ schema: DescItem[];
+ /**
+ * 数据
+ * @type object
+ */
+ data: Recordable;
+}
+
+export interface DescInstance {
+ setDescProps(descProps: Partial): void;
+}
+
+export type Register = (descInstance: DescInstance) => void;
+
+/**
+ * @description:
+ */
+export type UseDescReturnType = [Register, DescInstance];
diff --git a/apps/web-antd/src/components/description/src/useDescription.ts b/apps/web-antd/src/components/description/src/useDescription.ts
new file mode 100644
index 00000000..27bb4f56
--- /dev/null
+++ b/apps/web-antd/src/components/description/src/useDescription.ts
@@ -0,0 +1,36 @@
+import type {
+ DescInstance,
+ DescriptionProps,
+ UseDescReturnType,
+} from './typing';
+
+import { getCurrentInstance, ref, unref } from 'vue';
+
+export function useDescription(
+ props?: Partial,
+): UseDescReturnType {
+ if (!getCurrentInstance()) {
+ throw new Error(
+ 'useDescription() can only be used inside setup() or functional components!',
+ );
+ }
+ const desc = ref(null);
+ const loaded = ref(false);
+
+ function register(instance: DescInstance) {
+ if (unref(loaded) && import.meta.env.PROD) {
+ return;
+ }
+ desc.value = instance;
+ props && instance.setDescProps(props);
+ loaded.value = true;
+ }
+
+ const methods: DescInstance = {
+ setDescProps: (descProps: Partial): void => {
+ unref(desc)?.setDescProps(descProps);
+ },
+ };
+
+ return [register, methods];
+}
diff --git a/apps/web-antd/src/views/monitor/cache/components/RedisDescription.vue b/apps/web-antd/src/views/monitor/cache/components/RedisDescription.vue
index f39e266b..fcc75d0c 100644
--- a/apps/web-antd/src/views/monitor/cache/components/RedisDescription.vue
+++ b/apps/web-antd/src/views/monitor/cache/components/RedisDescription.vue
@@ -1,65 +1,104 @@
-
-
- {{ data.redis_version }}
-
-
- {{ data.redis_mode === 'standalone' ? '单机模式' : '集群模式' }}
-
-
- {{ data.tcp_port }}
-
-
- {{ data.connected_clients }}
-
-
- {{ `${data.uptime_in_days}天` }}
-
-
- {{ data.used_memory_human }}
-
-
- {{ parseFloat(data.used_cpu_user_children!).toFixed(2) }}
-
-
- {{ data.maxmemory_human }}
-
-
- {{ data.aof_enabled === '0' ? '否' : '是' }}
-
-
- {{ data.rdb_last_bgsave_status }}
-
-
- {{ data.dbSize }}
-
-
- {{
- `${data.instantaneous_input_kbps}kps/${data.instantaneous_output_kbps}kps`
- }}
-
-
+