/** * 通用组件共同的使用的基础组件,原先放在 adapter/form 内部,限制了使用范围,这里提取出来,方便其他地方使用 * 可用于 vben-form、vben-modal、vben-drawer 等组件使用, */ import type { Component } from 'vue'; import type { BaseFormComponentType } from '@vben/common-ui'; import type { Recordable } from '@vben/types'; import { computed, defineAsyncComponent, defineComponent, h, ref } from 'vue'; import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui'; import { $t } from '@vben/locales'; import { notification } from 'antdv-next'; import { FileUploadOld, ImageUploadOld } from '#/components/upload-old'; const RichTextarea = defineAsyncComponent(() => import('#/components/tinymce/index').then((res) => res.Tinymce), ); const FileUpload = defineAsyncComponent(() => import('#/components/upload').then((res) => res.FileUpload), ); const ImageUpload = defineAsyncComponent(() => import('#/components/upload').then((res) => res.ImageUpload), ); const Button = defineAsyncComponent( () => import('antdv-next/dist/button/index'), ); const Cascader = defineAsyncComponent( () => import('antdv-next/dist/cascader/index'), ); const Checkbox = defineAsyncComponent( () => import('antdv-next/dist/checkbox/index'), ); const CheckboxGroup = defineAsyncComponent( () => import('antdv-next/dist/checkbox/Group'), ); const DatePicker = defineAsyncComponent( () => import('antdv-next/dist/date-picker/index'), ); const Divider = defineAsyncComponent( () => import('antdv-next/dist/divider/index'), ); const Input = defineAsyncComponent(() => import('antdv-next/dist/input/index')); const InputNumber = defineAsyncComponent( () => import('antdv-next/dist/input-number/index'), ); const InputPassword = defineAsyncComponent( () => import('antdv-next/dist/input/Password'), ); const Mentions = defineAsyncComponent( () => import('antdv-next/dist/mentions/index'), ); const Radio = defineAsyncComponent(() => import('antdv-next/dist/radio/index')); const RadioGroup = defineAsyncComponent(() => import('antdv-next/dist/radio/index').then((res) => res.RadioGroup), ); const RangePicker = defineAsyncComponent(() => import('antdv-next/dist/date-picker/index').then( (res) => res.DateRangePicker, ), ); const Rate = defineAsyncComponent(() => import('antdv-next/dist/rate/index')); const Select = defineAsyncComponent( () => import('antdv-next/dist/select/index'), ); const Space = defineAsyncComponent(() => import('antdv-next/dist/space/index')); const Switch = defineAsyncComponent( () => import('antdv-next/dist/switch/index'), ); const Textarea = defineAsyncComponent( () => import('antdv-next/dist/input/TextArea'), ); const TimePicker = defineAsyncComponent( () => import('antdv-next/dist/time-picker/index'), ); const TimeRangePicker = defineAsyncComponent(() => import('antdv-next/dist/time-picker/index').then( (res) => res.TimeRangePicker, ), ); const TreeSelect = defineAsyncComponent( () => import('antdv-next/dist/tree-select/index'), ); const Upload = defineAsyncComponent( () => import('antdv-next/dist/upload/Upload'), ); const withDefaultPlaceholder = ( component: T, type: 'input' | 'select', componentProps: Recordable = {}, ) => { return defineComponent({ name: component.name, inheritAttrs: false, setup: (props: any, { attrs, expose, slots }) => { // 改为placeholder 解决在keepalive & 语言切换 & tab切换 显示不变的问题 const computedPlaceholder = computed( () => props?.placeholder || attrs?.placeholder || $t(`ui.placeholder.${type}`), ); // 透传组件暴露的方法 const innerRef = ref(); expose( new Proxy( {}, { get: (_target, key) => innerRef.value?.[key], has: (_target, key) => key in (innerRef.value || {}), }, ), ); return () => h( component, { ...componentProps, placeholder: computedPlaceholder.value, ...props, ...attrs, ref: innerRef, variant: 'outlined', }, slots, ); }, }); }; // 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明 export type ComponentType = | 'ApiCascader' | 'ApiSelect' | 'ApiTreeSelect' | 'AutoComplete' | 'Cascader' | 'Checkbox' | 'CheckboxGroup' | 'DatePicker' | 'DefaultButton' | 'Divider' | 'FileUpload' | 'FileUploadOld' | 'IconPicker' | 'ImageUpload' | 'ImageUploadOld' | 'Input' | 'InputNumber' | 'InputPassword' | 'Mentions' | 'PrimaryButton' | 'Radio' | 'RadioGroup' | 'RangePicker' | 'Rate' | 'RichTextarea' | 'Select' | 'Space' | 'Switch' | 'Textarea' | 'TimePicker' | 'TimeRangePicker' | 'TreeSelect' | 'Upload' | BaseFormComponentType; async function initComponentAdapter() { const components: Partial> = { // 如果你的组件体积比较大,可以使用异步加载 // Button: () => // import('xxx').then((res) => res.Button), ApiCascader: withDefaultPlaceholder(ApiComponent, 'select', { component: Cascader, fieldNames: { label: 'label', value: 'value', children: 'children' }, loadingSlot: 'suffixIcon', modelPropName: 'value', visibleEvent: 'onVisibleChange', }), ApiSelect: withDefaultPlaceholder( { ...ApiComponent, name: 'ApiSelect', }, 'select', { component: Select, loadingSlot: 'suffixIcon', visibleEvent: 'onDropdownVisibleChange', modelPropName: 'value', }, ), ApiTreeSelect: withDefaultPlaceholder( { ...ApiComponent, name: 'ApiTreeSelect', }, 'select', { component: TreeSelect, fieldNames: { label: 'label', value: 'value', children: 'children' }, loadingSlot: 'suffixIcon', modelPropName: 'value', optionsPropName: 'treeData', visibleEvent: 'onVisibleChange', }, ), Cascader: withDefaultPlaceholder(Cascader, 'select'), Checkbox, CheckboxGroup, DatePicker, // 自定义默认按钮 DefaultButton: (props, { attrs, slots }) => { return h(Button, { ...props, attrs, type: 'default' }, slots); }, Divider, IconPicker: withDefaultPlaceholder(IconPicker, 'select', { iconSlot: 'addonAfter', inputComponent: Input, modelValueProp: 'value', }), Input: withDefaultPlaceholder(Input, 'input'), InputNumber: withDefaultPlaceholder(InputNumber, 'input'), InputPassword: withDefaultPlaceholder(InputPassword, 'input'), Mentions: withDefaultPlaceholder(Mentions, 'input'), // 自定义主要按钮 PrimaryButton: (props, { attrs, slots }) => { return h(Button, { ...props, attrs, type: 'primary' }, slots); }, Radio, RadioGroup, RangePicker, Rate, Select: withDefaultPlaceholder(Select, 'select'), Space, Switch, Textarea: withDefaultPlaceholder(Textarea, 'input'), TimePicker, TimeRangePicker, TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'), Upload, ImageUpload, FileUpload, RichTextarea, ImageUploadOld, FileUploadOld, }; // 将组件注册到全局共享状态中 globalShareState.setComponents(components); // 定义全局共享状态中的消息提示 globalShareState.defineMessage({ // 复制成功消息提示 copyPreferencesSuccess: (title, content) => { notification.success({ description: content, title, placement: 'bottomRight', }); }, }); } export { initComponentAdapter };