sunmao-sdk
Version:
榫卯-开箱即用赋能-sdk
204 lines (188 loc) • 6.09 kB
JavaScript
;
import React, { useState, useEffect, useRef } from "react";
import { Select, Spin } from "antd";
import { getFirstList, toStringArray } from "../../utils/commonUtils";
import { getDicTrue, getId, getName, getDisabled } from "../../utils/formUtils";
import { isEmpty, isInteger, debounce } from "lodash";
const { Option } = Select;
/**
* commonProps 独立配置
* showSearch : 是否可输入搜索,默认否 openSearch
* requestFunc : 外部传进网络请求方法,只能接受返回数组[] ,切记
* url : 如需网络获取选择列表,需提供url
* params : 网络请求参数
*
* list : 默认选择列表
* key : 对象key对应字段,即返回的value
* text : 对象name对应字段,即显示的name
* showName : 对象name对应字段,即显示的name
* specialReturn : 特殊返回函数,进行特殊处理,如不止需要返回选中 value时,可通过此方法返回,返回为数组或对象,结合antd的API,自行注意
*
*
* uiOptions 为antd中Select自带属性,参考antd中API
*
* bs:func 传值,不能被转json后
*/
const displayName = "SelectCommon";
const SelectCommon = props => {
const {
onChange,
name,
value,
schema: { commonProps = {} },
options: uiOptions,
rootValue,
...otherProps
} = props;
const selectValue = toStringArray(value);
const {
openSearch = false,
formToReq = false, // 开启搜索时,表单作为参数请求
strictSearch = true, // 严格搜索选项
inputToSelect = false, // 输入即选中
labelInValue,
requestFunc,
url,
params,
list,
key = "key",
text = "preName",
disabledKey = "disabled",
showName,
defaultSelect,
okPath,
specialReturn
} = commonProps;
// 组件单独使用 与 榫卯平台配置 兼容处理 开放搜索
const showSearch = openSearch === true || getDicTrue(openSearch);
// 开放搜索时,将表单数据带入请求
const formDataToReq =
showSearch && (formToReq === true || getDicTrue(formToReq));
const [state, set] = useState([]);
const [fetching, setFetch] = useState(false);
const listString = useRef(null);
useEffect(() => {
if (list) setList(list);
//需要网络请求
else if (url && requestFunc) {
post("");
}
}, []);
useEffect(() => {
const listToString = JSON.stringify(list);
if (!isEmpty(list) && listString.current != listToString) {
listString.current = listToString;
setList(list);
}
}, [list]);
const post = async data => {
let reqParams;
if (showSearch) {
if (formDataToReq) {
reqParams = { ...rootValue };
}
//组装请求参数
reqParams = { ...reqParams, keyWord: data, searchKey: data, ...params };
// 支持按name搜索,不支持按key
labelInValue && (reqParams[labelInValue] = data);
}
if (requestFunc) {
setFetch(true);
requestFunc(url, reqParams || params, okPath).then(req => {
const list = getFirstList(req);
if (!isEmpty(list)) {
setList(list);
} else if (data && (!strictSearch || params?.noStrictSearch)) {
// 非严谨搜索则将输入当成选项
const item = { key: data, value: data };
item[key] = data;
item[text] = data;
setList([item]);
if (inputToSelect) {
// 输入即选中, 模拟选中操作
handleChange(data, { ...item, other: item, children: data });
}
}
setFetch(false);
});
} else if (data && (!strictSearch || params?.noStrictSearch)) {
// 非严谨搜索则将输入当成选项
const item = { key: data, value: data };
item[key] = data;
item[text] = data;
setList([item, ...list]);
if (inputToSelect) {
// 输入即选中, 模拟选中操作
handleChange(data, { ...item, other: item, children: data });
}
}
};
const setList = list => {
// 只支持下拉单选
if (defaultSelect) {
const value = { value: list.length ? getId(list[0], key) : null };
for (const item of list) {
const keyValue = getId(item, key);
if (keyValue === defaultSelect) {
value.value = keyValue;
value.other = item;
break;
}
}
// formRender 的 onChange 只支持单一调用,当多item同时调用,会覆盖之前操作
// 此为单一组件开放入口,不支持formRender
onChange && onChange(name, value.value);
specialReturn && specialReturn(value, true);
}
set(list);
};
const handleChange = (value, other) => {
let obj = null;
if (labelInValue) {
obj = { ...rootValue };
obj[labelInValue] = other?.children || null;
// name优先级高于labelInValue
obj[name] = value?.length ? value : null;
}
onChange && onChange(name, value?.length ? value : null, obj);
//需特殊返回,则将选中对象返回,前置自行处理,可能返回空数组
if (specialReturn) {
specialReturn(other);
}
try {
showSearch && navigator.clipboard.writeText(other?.children);
} catch {}
};
return (
<Select
style={{ width: "100%" }}
value={
isInteger(selectValue)
? `${selectValue}`
: selectValue
? selectValue
: []
}
allowClear
filterOption={false}
notFoundContent={fetching ? <Spin size="small" /> : null}
onChange={handleChange}
showSearch={showSearch}
onSearch={showSearch ? debounce(post, 500) : null}
placeholder={showSearch ? "请输入搜索" : "请选择"}
{...uiOptions}
>
{!fetching &&
state?.map(i => (
<Option
key={getId(i, key)}
other={i}
disabled={getDisabled(i, disabledKey)}
>
{showName ? showName(i) : getName(i, text) || getId(i, key)}
</Option>
))}
</Select>
);
};
export default SelectCommon;