index.ts 6.3 KB

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