index.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /**
  2. * 通用组件共同的使用的基础组件,原先放在 adapter/form 内部,限制了使用范围,这里提取出来,方便其他地方使用
  3. * 可用于 vben-form、vben-modal、vben-drawer 等组件使用,
  4. */
  5. import type { Component } from 'vue';
  6. import type { BaseFormComponentType } from '@vben/common-ui';
  7. import type { Recordable } from '@vben/types';
  8. import { defineAsyncComponent, defineComponent, h, ref } from 'vue';
  9. import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui';
  10. import { $t } from '@vben/locales';
  11. import { notification } from 'ant-design-vue';
  12. const AutoComplete = defineAsyncComponent(
  13. () => import('ant-design-vue/es/auto-complete'),
  14. );
  15. const Button = defineAsyncComponent(() => import('ant-design-vue/es/button'));
  16. const Checkbox = defineAsyncComponent(
  17. () => import('ant-design-vue/es/checkbox'),
  18. );
  19. const CheckboxGroup = defineAsyncComponent(() =>
  20. import('ant-design-vue/es/checkbox').then((res) => res.CheckboxGroup),
  21. );
  22. const DatePicker = defineAsyncComponent(
  23. () => import('ant-design-vue/es/date-picker'),
  24. );
  25. const Divider = defineAsyncComponent(() => import('ant-design-vue/es/divider'));
  26. const Input = defineAsyncComponent(() => import('ant-design-vue/es/input'));
  27. const InputNumber = defineAsyncComponent(
  28. () => import('ant-design-vue/es/input-number'),
  29. );
  30. const InputPassword = defineAsyncComponent(() =>
  31. import('ant-design-vue/es/input').then((res) => res.InputPassword),
  32. );
  33. const Mentions = defineAsyncComponent(
  34. () => import('ant-design-vue/es/mentions'),
  35. );
  36. const Radio = defineAsyncComponent(() => import('ant-design-vue/es/radio'));
  37. const RadioGroup = defineAsyncComponent(() =>
  38. import('ant-design-vue/es/radio').then((res) => res.RadioGroup),
  39. );
  40. const RangePicker = defineAsyncComponent(() =>
  41. import('ant-design-vue/es/date-picker').then((res) => res.RangePicker),
  42. );
  43. const Rate = defineAsyncComponent(() => import('ant-design-vue/es/rate'));
  44. const Select = defineAsyncComponent(() => import('ant-design-vue/es/select'));
  45. const Space = defineAsyncComponent(() => import('ant-design-vue/es/space'));
  46. const Switch = defineAsyncComponent(() => import('ant-design-vue/es/switch'));
  47. const Textarea = defineAsyncComponent(() =>
  48. import('ant-design-vue/es/input').then((res) => res.Textarea),
  49. );
  50. const TimePicker = defineAsyncComponent(
  51. () => import('ant-design-vue/es/time-picker'),
  52. );
  53. const TreeSelect = defineAsyncComponent(
  54. () => import('ant-design-vue/es/tree-select'),
  55. );
  56. const Upload = defineAsyncComponent(() => import('ant-design-vue/es/upload'));
  57. const withDefaultPlaceholder = <T extends Component>(
  58. component: T,
  59. type: 'input' | 'select',
  60. componentProps: Recordable<any> = {},
  61. ) => {
  62. return defineComponent({
  63. name: component.name,
  64. inheritAttrs: false,
  65. setup: (props: any, { attrs, expose, slots }) => {
  66. const placeholder =
  67. props?.placeholder ||
  68. attrs?.placeholder ||
  69. $t(`ui.placeholder.${type}`);
  70. // 透传组件暴露的方法
  71. const innerRef = ref();
  72. expose(
  73. new Proxy(
  74. {},
  75. {
  76. get: (_target, key) => innerRef.value?.[key],
  77. has: (_target, key) => key in (innerRef.value || {}),
  78. },
  79. ),
  80. );
  81. return () =>
  82. h(
  83. component,
  84. { ...componentProps, placeholder, ...props, ...attrs, ref: innerRef },
  85. slots,
  86. );
  87. },
  88. });
  89. };
  90. // 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明
  91. export type ComponentType =
  92. | 'ApiSelect'
  93. | 'ApiTreeSelect'
  94. | 'AutoComplete'
  95. | 'Checkbox'
  96. | 'CheckboxGroup'
  97. | 'DatePicker'
  98. | 'DefaultButton'
  99. | 'Divider'
  100. | 'IconPicker'
  101. | 'Input'
  102. | 'InputNumber'
  103. | 'InputPassword'
  104. | 'Mentions'
  105. | 'PrimaryButton'
  106. | 'Radio'
  107. | 'RadioGroup'
  108. | 'RangePicker'
  109. | 'Rate'
  110. | 'Select'
  111. | 'Space'
  112. | 'Switch'
  113. | 'Textarea'
  114. | 'TimePicker'
  115. | 'TreeSelect'
  116. | 'Upload'
  117. | BaseFormComponentType;
  118. async function initComponentAdapter() {
  119. const components: Partial<Record<ComponentType, Component>> = {
  120. // 如果你的组件体积比较大,可以使用异步加载
  121. // Button: () =>
  122. // import('xxx').then((res) => res.Button),
  123. ApiSelect: withDefaultPlaceholder(
  124. {
  125. ...ApiComponent,
  126. name: 'ApiSelect',
  127. },
  128. 'select',
  129. {
  130. component: Select,
  131. loadingSlot: 'suffixIcon',
  132. visibleEvent: 'onDropdownVisibleChange',
  133. modelPropName: 'value',
  134. },
  135. ),
  136. ApiTreeSelect: withDefaultPlaceholder(
  137. {
  138. ...ApiComponent,
  139. name: 'ApiTreeSelect',
  140. },
  141. 'select',
  142. {
  143. component: TreeSelect,
  144. fieldNames: { label: 'label', value: 'value', children: 'children' },
  145. loadingSlot: 'suffixIcon',
  146. modelPropName: 'value',
  147. optionsPropName: 'treeData',
  148. visibleEvent: 'onVisibleChange',
  149. },
  150. ),
  151. AutoComplete,
  152. Checkbox,
  153. CheckboxGroup,
  154. DatePicker,
  155. // 自定义默认按钮
  156. DefaultButton: (props, { attrs, slots }) => {
  157. return h(Button, { ...props, attrs, type: 'default' }, slots);
  158. },
  159. Divider,
  160. IconPicker: withDefaultPlaceholder(IconPicker, 'select', {
  161. iconSlot: 'addonAfter',
  162. inputComponent: Input,
  163. modelValueProp: 'value',
  164. }),
  165. Input: withDefaultPlaceholder(Input, 'input'),
  166. InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
  167. InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
  168. Mentions: withDefaultPlaceholder(Mentions, 'input'),
  169. // 自定义主要按钮
  170. PrimaryButton: (props, { attrs, slots }) => {
  171. return h(Button, { ...props, attrs, type: 'primary' }, slots);
  172. },
  173. Radio,
  174. RadioGroup,
  175. RangePicker,
  176. Rate,
  177. Select: withDefaultPlaceholder(Select, 'select'),
  178. Space,
  179. Switch,
  180. Textarea: withDefaultPlaceholder(Textarea, 'input'),
  181. TimePicker,
  182. TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'),
  183. Upload,
  184. };
  185. // 将组件注册到全局共享状态中
  186. globalShareState.setComponents(components);
  187. // 定义全局共享状态中的消息提示
  188. globalShareState.defineMessage({
  189. // 复制成功消息提示
  190. copyPreferencesSuccess: (title, content) => {
  191. notification.success({
  192. description: content,
  193. message: title,
  194. placement: 'bottomRight',
  195. });
  196. },
  197. });
  198. }
  199. export { initComponentAdapter };