useAdvanced.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import type { ColEx } from '../types';
  2. import type { AdvanceState } from '../types/hooks';
  3. import type { ComputedRef, Ref } from 'vue';
  4. import type { FormProps, FormSchema } from '../types/form';
  5. import { computed, unref, watch } from 'vue';
  6. import { isBoolean, isFunction, isNumber, isObject } from '/@/utils/is';
  7. import { useBreakpoint } from '/@/hooks/event/useBreakpoint';
  8. import { useDebounceFn } from '@vueuse/core';
  9. const BASIC_COL_LEN = 24;
  10. interface UseAdvancedContext {
  11. advanceState: AdvanceState;
  12. emit: EmitType;
  13. getProps: ComputedRef<FormProps>;
  14. getSchema: ComputedRef<FormSchema[]>;
  15. formModel: Recordable;
  16. defaultValueRef: Ref<Recordable>;
  17. }
  18. export default function ({
  19. advanceState,
  20. emit,
  21. getProps,
  22. getSchema,
  23. formModel,
  24. defaultValueRef,
  25. }: UseAdvancedContext) {
  26. const { realWidthRef, screenEnum, screenRef } = useBreakpoint();
  27. const getEmptySpan = computed((): number => {
  28. if (!advanceState.isAdvanced) {
  29. return 0;
  30. }
  31. // For some special cases, you need to manually specify additional blank lines
  32. const emptySpan = unref(getProps).emptySpan || 0;
  33. if (isNumber(emptySpan)) {
  34. return emptySpan;
  35. }
  36. if (isObject(emptySpan)) {
  37. const { span = 0 } = emptySpan;
  38. const screen = unref(screenRef) as string;
  39. const screenSpan = (emptySpan as any)[screen.toLowerCase()];
  40. return screenSpan || span || 0;
  41. }
  42. return 0;
  43. });
  44. const debounceUpdateAdvanced = useDebounceFn(updateAdvanced, 30);
  45. watch(
  46. [
  47. // TODO
  48. // () => unref(getSchema),
  49. () => advanceState.isAdvanced,
  50. () => unref(realWidthRef),
  51. ],
  52. () => {
  53. const { showAdvancedButton } = unref(getProps);
  54. if (showAdvancedButton) {
  55. debounceUpdateAdvanced();
  56. }
  57. },
  58. { immediate: true }
  59. );
  60. function getAdvanced(itemCol: Partial<ColEx>, itemColSum = 0, isLastAction = false) {
  61. const width = unref(realWidthRef);
  62. const mdWidth =
  63. parseInt(itemCol.md as string) ||
  64. parseInt(itemCol.xs as string) ||
  65. parseInt(itemCol.sm as string) ||
  66. (itemCol.span as number) ||
  67. BASIC_COL_LEN;
  68. const lgWidth = parseInt(itemCol.lg as string) || mdWidth;
  69. const xlWidth = parseInt(itemCol.xl as string) || lgWidth;
  70. const xxlWidth = parseInt(itemCol.xxl as string) || xlWidth;
  71. if (width <= screenEnum.LG) {
  72. itemColSum += mdWidth;
  73. } else if (width < screenEnum.XL) {
  74. itemColSum += lgWidth;
  75. } else if (width < screenEnum.XXL) {
  76. itemColSum += xlWidth;
  77. } else {
  78. itemColSum += xxlWidth;
  79. }
  80. if (isLastAction) {
  81. advanceState.hideAdvanceBtn = false;
  82. if (itemColSum <= BASIC_COL_LEN * 2) {
  83. // When less than or equal to 2 lines, the collapse and expand buttons are not displayed
  84. advanceState.hideAdvanceBtn = true;
  85. advanceState.isAdvanced = true;
  86. } else if (
  87. itemColSum > BASIC_COL_LEN * 2 &&
  88. itemColSum <= BASIC_COL_LEN * (unref(getProps).autoAdvancedLine || 3)
  89. ) {
  90. advanceState.hideAdvanceBtn = false;
  91. // More than 3 lines collapsed by default
  92. } else if (!advanceState.isLoad) {
  93. advanceState.isLoad = true;
  94. advanceState.isAdvanced = !advanceState.isAdvanced;
  95. }
  96. return { isAdvanced: advanceState.isAdvanced, itemColSum };
  97. }
  98. if (itemColSum > BASIC_COL_LEN) {
  99. return { isAdvanced: advanceState.isAdvanced, itemColSum };
  100. } else {
  101. // The first line is always displayed
  102. return { isAdvanced: true, itemColSum };
  103. }
  104. }
  105. function updateAdvanced() {
  106. let itemColSum = 0;
  107. let realItemColSum = 0;
  108. const { baseColProps = {} } = unref(getProps);
  109. for (const schema of unref(getSchema)) {
  110. const { show, colProps } = schema;
  111. let isShow = true;
  112. if (isBoolean(show)) {
  113. isShow = show;
  114. }
  115. if (isFunction(show)) {
  116. isShow = show({
  117. schema: schema,
  118. model: formModel,
  119. field: schema.field,
  120. values: {
  121. ...unref(defaultValueRef),
  122. ...formModel,
  123. },
  124. });
  125. }
  126. if (isShow && (colProps || baseColProps)) {
  127. const { itemColSum: sum, isAdvanced } = getAdvanced(
  128. { ...baseColProps, ...colProps },
  129. itemColSum
  130. );
  131. itemColSum = sum || 0;
  132. if (isAdvanced) {
  133. realItemColSum = itemColSum;
  134. }
  135. schema.isAdvanced = isAdvanced;
  136. }
  137. }
  138. advanceState.actionSpan = (realItemColSum % BASIC_COL_LEN) + unref(getEmptySpan);
  139. getAdvanced(unref(getProps).actionColOptions || { span: BASIC_COL_LEN }, itemColSum, true);
  140. emit('advanced-change');
  141. }
  142. function handleToggleAdvanced() {
  143. advanceState.isAdvanced = !advanceState.isAdvanced;
  144. }
  145. return { handleToggleAdvanced };
  146. }