Просмотр исходного кода

feat: 添加ApiCheckboxGroup 组件

fan 2 лет назад
Родитель
Сommit
afbc094111

+ 118 - 0
src/components/Form/src/components/ApiCheckboxGroup.vue

@@ -0,0 +1,118 @@
+<!--
+ * @Description:It is troublesome to implement Checkbox button group in the form. So it is extracted independently as a separate component
+-->
+<template>
+  <CheckboxGroup v-bind="attrs" v-model:value="state" @change="handleChange">
+    <template v-for="item in getOptions" :key="`${item.value}`">
+      <Checkbox :value="item.value" :disabled="item.disabled">
+        {{ item.label }}
+      </Checkbox>
+    </template>
+  </CheckboxGroup>
+</template>
+<script lang="ts">
+  import { defineComponent, PropType, ref, watchEffect, computed, unref, watch } from 'vue';
+  import { Checkbox, CheckboxGroup } from 'ant-design-vue';
+  import { isFunction } from '/@/utils/is';
+  import { useRuleFormItem } from '/@/hooks/component/useFormItem';
+  import { useAttrs } from '/@/hooks/core/useAttrs';
+  import { propTypes } from '/@/utils/propTypes';
+  import { get, omit } from 'lodash-es';
+  type OptionsItem = { label: string; value: string | number | boolean; disabled?: boolean };
+
+  export default defineComponent({
+    name: 'ApiCheckboxGroup',
+    components: {
+      CheckboxGroup,
+      Checkbox,
+    },
+    props: {
+      api: {
+        type: Function as PropType<(arg?: Recordable | string) => Promise<OptionsItem[]>>,
+        default: null,
+      },
+      params: {
+        type: [Object, String] as PropType<Recordable | string>,
+        default: () => ({}),
+      },
+      value: [Array, Object, String, Number],
+      numberToString: propTypes.bool,
+      resultField: propTypes.string.def(''),
+      labelField: propTypes.string.def('label'),
+      valueField: propTypes.string.def('value'),
+      immediate: propTypes.bool.def(true),
+    },
+    emits: ['options-change', 'change'],
+    setup(props, { emit }) {
+      const options = ref<OptionsItem[]>([]);
+      const loading = ref(false);
+      const isFirstLoad = ref(true);
+      const emitData = ref<any[]>([]);
+      const attrs = useAttrs();
+      // Embedded in the form, just use the hook binding to perform form verification
+      const [state] = useRuleFormItem(props);
+
+      // Processing options value
+      const getOptions = computed(() => {
+        const { labelField, valueField, numberToString } = props;
+
+        return unref(options).reduce((prev, next: Recordable) => {
+          if (next) {
+            const value = next[valueField];
+            prev.push({
+              label: next[labelField],
+              value: numberToString ? `${value}` : value,
+              ...omit(next, [labelField, valueField]),
+            });
+          }
+          return prev;
+        }, [] as OptionsItem[]);
+      });
+
+      watchEffect(() => {
+        props.immediate && fetch();
+      });
+
+      watch(
+        () => props.params,
+        () => {
+          !unref(isFirstLoad) && fetch();
+        },
+        { deep: true },
+      );
+
+      async function fetch() {
+        const api = props.api;
+        if (!api || !isFunction(api)) return;
+        options.value = [];
+        try {
+          loading.value = true;
+          const res = await api(props.params);
+          if (Array.isArray(res)) {
+            options.value = res;
+            emitChange();
+            return;
+          }
+          if (props.resultField) {
+            options.value = get(res, props.resultField) || [];
+          }
+          emitChange();
+        } catch (error) {
+          console.warn(error);
+        } finally {
+          loading.value = false;
+        }
+      }
+
+      function emitChange() {
+        emit('options-change', unref(getOptions));
+      }
+
+      function handleChange(_, ...args) {
+        emitData.value = args;
+      }
+
+      return { state, getOptions, attrs, loading, handleChange, props };
+    },
+  });
+</script>

+ 1 - 1
src/components/Form/src/hooks/useFormEvents.ts

@@ -107,7 +107,7 @@ export function useFormEvents({
         });
       }
     });
-    validateFields(validKeys).catch(_ => { });
+    validateFields(validKeys).catch(_ => {});
   }
   /**
    * @description: Delete based on field name

+ 1 - 0
src/components/Form/src/types/index.ts

@@ -94,6 +94,7 @@ export type ComponentType =
   | 'ApiTree'
   | 'ApiTreeSelect'
   | 'ApiRadioGroup'
+  | 'ApiCheckboxGroup'
   | 'RadioButtonGroup'
   | 'RadioGroup'
   | 'Checkbox'