diff --git a/apps/web-antd/src/components/description/description.vue b/apps/web-antd/src/components/description/description.vue
new file mode 100644
index 000000000..411333778
--- /dev/null
+++ b/apps/web-antd/src/components/description/description.vue
@@ -0,0 +1,71 @@
+
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 000000000..a707c4865
--- /dev/null
+++ b/apps/web-antd/src/components/description/index.ts
@@ -0,0 +1,3 @@
+export { default as Description } from './description.vue';
+export * from './typing';
+export { useDescription } from './use-description';
diff --git a/apps/web-antd/src/components/description/typing.ts b/apps/web-antd/src/components/description/typing.ts
new file mode 100644
index 000000000..98e3a52d1
--- /dev/null
+++ b/apps/web-antd/src/components/description/typing.ts
@@ -0,0 +1,18 @@
+import type { DescriptionsProps } from 'ant-design-vue';
+import type { CSSProperties, VNode } from 'vue';
+
+export interface DescriptionItemSchema {
+ label: string | VNode; // 内容的描述
+ field?: string; // 对应 data 中的字段名
+ content?: ((data: any) => string | VNode) | string | VNode; // 自定义需要展示的内容,比如说 dict-tag
+ span?: number; // 包含列的数量
+ labelStyle?: CSSProperties; // 自定义标签样式
+ contentStyle?: CSSProperties; // 自定义内容样式
+ hidden?: ((data: any) => boolean) | boolean; // 是否显示
+}
+
+export interface DescriptionsOptions {
+ data?: Record; // 数据
+ schema?: DescriptionItemSchema[]; // 描述项配置
+ componentProps?: DescriptionsProps; // antd Descriptions 组件参数
+}
diff --git a/apps/web-antd/src/components/description/use-description.ts b/apps/web-antd/src/components/description/use-description.ts
new file mode 100644
index 000000000..8cf44ccfa
--- /dev/null
+++ b/apps/web-antd/src/components/description/use-description.ts
@@ -0,0 +1,70 @@
+import type { DescriptionsOptions } from './typing';
+
+import { defineComponent, h, isReactive, reactive, watch } from 'vue';
+
+import { Description } from './index';
+
+/** 描述列表 api 定义 */
+class DescriptionApi {
+ private state = reactive>({});
+
+ constructor(options: DescriptionsOptions) {
+ this.state = { ...options };
+ }
+
+ getState(): DescriptionsOptions {
+ return this.state as DescriptionsOptions;
+ }
+
+ setState(newState: Partial) {
+ this.state = { ...this.state, ...newState };
+ }
+}
+
+export type ExtendedDescriptionApi = DescriptionApi;
+
+export function useDescription(options: DescriptionsOptions) {
+ const IS_REACTIVE = isReactive(options);
+ const api = new DescriptionApi(options);
+ // 扩展API
+ const extendedApi: ExtendedDescriptionApi = api as never;
+ const Desc = defineComponent({
+ name: 'UseDescription',
+ inheritAttrs: false,
+ setup(_, { attrs, slots }) {
+ // 合并props和attrs到state
+ api.setState({ ...attrs });
+
+ return () =>
+ h(
+ Description,
+ {
+ ...api.getState(),
+ ...attrs,
+ },
+ slots,
+ );
+ },
+ });
+
+ // 响应式支持
+ if (IS_REACTIVE) {
+ watch(
+ () => options.schema,
+ (newSchema) => {
+ api.setState({ schema: newSchema });
+ },
+ { immediate: true, deep: true },
+ );
+
+ watch(
+ () => options.data,
+ (newData) => {
+ api.setState({ data: newData });
+ },
+ { immediate: true, deep: true },
+ );
+ }
+
+ return [Desc, extendedApi] as const;
+}
diff --git a/apps/web-antd/src/views/system/notify/my/modules/detail.vue b/apps/web-antd/src/views/system/notify/my/modules/detail.vue
index cdad97dae..2c5275c35 100644
--- a/apps/web-antd/src/views/system/notify/my/modules/detail.vue
+++ b/apps/web-antd/src/views/system/notify/my/modules/detail.vue
@@ -1,18 +1,56 @@
-
-
-
- {{ formData?.templateNickname }}
-
-
- {{ formatDateTime(formData?.createTime) }}
-
-
-
-
-
-
-
-
- {{ formatDateTime(formData?.readTime || '') }}
-
-
- {{ formData?.templateContent }}
-
-
+
+