diff --git a/apps/web-antd/package.json b/apps/web-antd/package.json index a703101ffee1d7981fb81c20581fcd943afd7a9b..d64639a1895229b7bf1fffbb55a4f4ffb8425f35 100644 --- a/apps/web-antd/package.json +++ b/apps/web-antd/package.json @@ -45,6 +45,7 @@ "@vben/utils": "workspace:*", "@vueuse/core": "catalog:", "ant-design-vue": "catalog:", + "vxe-table": "catalog:", "cropperjs": "catalog:", "crypto-js": "catalog:", "dayjs": "catalog:", diff --git a/apps/web-antd/src/bootstrap.ts b/apps/web-antd/src/bootstrap.ts index 761e58ed2d09cdc6180d16f89e748b68685700b0..084051d4e51ced94ca5292c42eeebdeb2cf10946 100644 --- a/apps/web-antd/src/bootstrap.ts +++ b/apps/web-antd/src/bootstrap.ts @@ -7,6 +7,7 @@ import { preferences } from '@vben/preferences'; import { initStores } from '@vben/stores'; import '@vben/styles'; import '@vben/styles/antd'; +import 'vxe-table/styles/cssvar.scss'; import { useTitle } from '@vueuse/core'; diff --git a/apps/web-antd/src/components/content-wrap/content-wrap.vue b/apps/web-antd/src/components/content-wrap/content-wrap.vue new file mode 100644 index 0000000000000000000000000000000000000000..026d7d23ff542036b3d3828d4d95cbe976a7811d --- /dev/null +++ b/apps/web-antd/src/components/content-wrap/content-wrap.vue @@ -0,0 +1,24 @@ + + + diff --git a/apps/web-antd/src/components/content-wrap/index.ts b/apps/web-antd/src/components/content-wrap/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..d4f95fddb0838fc99e81a84f30f70a4a1bb97765 --- /dev/null +++ b/apps/web-antd/src/components/content-wrap/index.ts @@ -0,0 +1 @@ +export { default as ContentWrap } from './content-wrap.vue'; 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 0000000000000000000000000000000000000000..41133377832304ba03a915f33b8fcdd594606f63 --- /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 0000000000000000000000000000000000000000..a707c486557880c088e1b4a4b0557f224c5ef039 --- /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 0000000000000000000000000000000000000000..98e3a52d1d10e22fb23d42555c3e0216a0241fc2 --- /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 0000000000000000000000000000000000000000..8cf44ccfaa1b1022c416793772b0e67cb86bc121 --- /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/utils/dict.ts b/apps/web-antd/src/utils/dict.ts index e647665b98e25e71021b378f051021370172fabd..4b6cf0db59e271943b0b9d01493d1a2cf0a59b6f 100644 --- a/apps/web-antd/src/utils/dict.ts +++ b/apps/web-antd/src/utils/dict.ts @@ -64,7 +64,7 @@ function getDictObj(dictType: string, value: any) { function getDictOptions( dictType: string, valueType: 'boolean' | 'number' | 'string' = 'string', -) { +): any[] { const dictStore = useDictStore(); const dictOpts = dictStore.getDictOptions(dictType); const dictOptions: DefaultOptionType = []; diff --git a/apps/web-antd/src/views/infra/demo/general/demo01/index.vue b/apps/web-antd/src/views/infra/demo/general/demo01/index.vue new file mode 100644 index 0000000000000000000000000000000000000000..01a8b5fab53c0ca82f1459dbce3de17572c905de --- /dev/null +++ b/apps/web-antd/src/views/infra/demo/general/demo01/index.vue @@ -0,0 +1,223 @@ + + + diff --git a/apps/web-antd/src/views/infra/demo/general/demo01/modules/form.vue b/apps/web-antd/src/views/infra/demo/general/demo01/modules/form.vue new file mode 100644 index 0000000000000000000000000000000000000000..8f95c804494a8d9ff9f77e5e90a6154a6f4e19d6 --- /dev/null +++ b/apps/web-antd/src/views/infra/demo/general/demo01/modules/form.vue @@ -0,0 +1,121 @@ + + + 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 cdad97daea27c8329a4e7789fb461d1b7e6a3627..2c5275c35ccecca5f0819d99831b49f4a928ebaf 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 @@ diff --git a/packages/@core/base/icons/src/lucide.ts b/packages/@core/base/icons/src/lucide.ts index 2a5de70bdbd32e6ff4e7cd4e52aff10a42bc0e90..21ac04e2e0f37b30c1c7e4a909fc3693655fb571 100644 --- a/packages/@core/base/icons/src/lucide.ts +++ b/packages/@core/base/icons/src/lucide.ts @@ -69,4 +69,5 @@ export { Upload, UserRoundPen, X, + RefreshCw, } from 'lucide-vue-next';