From e519bff27cb94bc8ce47403d7ff5b992935904a6 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 25 Apr 2025 18:18:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E6=94=AF=E6=8C=81=20?= =?UTF-8?q?schema=20=E6=A8=A1=E5=BC=8F=E7=9A=84=E6=8F=8F=E8=BF=B0=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/description/description.vue | 71 +++++++++++++++ .../src/components/description/index.ts | 3 + .../src/components/description/typing.ts | 18 ++++ .../components/description/use-description.ts | 70 +++++++++++++++ .../views/system/notify/my/modules/detail.vue | 86 +++++++++++-------- 5 files changed, 210 insertions(+), 38 deletions(-) create mode 100644 apps/web-antd/src/components/description/description.vue create mode 100644 apps/web-antd/src/components/description/index.ts create mode 100644 apps/web-antd/src/components/description/typing.ts create mode 100644 apps/web-antd/src/components/description/use-description.ts 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 @@