Default.tsx 3.68 KB
import { useState } from 'react';
import MySelect from '../my-select';
import type {
  subGlobalProps,
} from '../index';
import {
  requestCode,
} from '@/services/server';
import type {
  objectProps,
  datasProps,
  propsProps,
} from './datas';

export interface DefaultProps {
  globalProps: subGlobalProps;
  findParam: any;
  rule: datasProps;
}


/**
 * 解析 findProps 参数
 */
export const getFindProps = (
  findProps: datasProps['find']['props'],
  apiProps: any
): propsProps | null => {
  let props: propsProps | null = null;
  if (findProps) {
    // eslint-disable-next-line no-restricted-syntax
    for (const key in findProps) {
      if (apiProps[key]) {
        props = findProps[key];
      }
    }
  }
  return props;
}

/**
 * 合并params 参数
 */
export const mergeParams = (
  apiParams: datasProps['find']['apiParams'],
  params: objectProps,
  name: string
): objectProps => {
  if (!apiParams) return { ...params, name };
  let serverParams: objectProps = {};
  if (typeof apiParams === 'function') {
    serverParams = apiParams(params, name);
  } else {
    serverParams = {
      ...params,
      ...apiParams,
      name,
    }
  }
  return serverParams;
}

/**
 * select 选择控件
 */
export default ({
  globalProps,
  rule,
  findParam,
  ...apiProps
}: DefaultProps) => {
  const { onChildError, placeholder, ...props } = globalProps;
  const {
    itemRender,
    find: { apiUrl, apiParams, apiResult, props: findProps },
    get,
  } = rule;

  const [{ params, title }] = useState<any>(() => {
    const obj: propsProps | null = getFindProps(findProps, apiProps);
    return {
      params: obj ? { ...obj.apiParams, ...findParam } : findParam,
      title: obj ? obj.title : rule.title,
    }
  });

  return <MySelect.Paging
    placeholder={placeholder || `请选择${title}`}
    {...props}
    serverParams={params}
    serverResult={async (param: any, name: string) => {
      const requestParams = mergeParams(apiParams, param, name)
      const data = await requestCode(apiUrl, requestParams);
      const key = apiResult || 'result';
      if (data[key]) {
        data.result = data[key].map((option: any) => {
          if (itemRender) {
            return itemRender(option);
          }
          return option;
        });
      }
      return data;
    }}
    onChildError={async (ids: string[], list: any[]) => {
      if (!get && onChildError) {
        if (props.mode === 'multiple' || props.mode === 'tags') {
          onChildError(ids, list);
        } else {
          onChildError(ids[0], list);
        }
        return null;
      }
      // eslint-disable-next-line @typescript-eslint/no-shadow
      const { apiUrl, apiResult, apiParams }: any = get;
      const result: any[] = await Promise.all(ids.map((id) => {
        return new Promise((resolve) => {
          let requestParams: any = { id };
          if (apiParams) requestParams = apiParams(requestParams);
          requestCode(apiUrl, requestParams).then((data: any) => {
            const key = apiResult || 'data';
            if (data[key]) {
              if (itemRender) {
                resolve(itemRender(data[key]));
              } else {
                resolve(data[key]);
              }
            } else {
              resolve(id);
            }
          }).finally(() => {
            resolve(id);
          })
        })
      }))
      const error: string[] = result.filter((item) => typeof item === 'string');
      if (error.length && onChildError) {
        if (props.mode === 'multiple' || props.mode === 'tags') {
          onChildError(error, list);
        } else {
          onChildError(error[0], list);
        }
      }
      return result.filter((item) => typeof item === 'object');
    }}
  />
}