弹窗组件封装
- 某一段代码过于庞大则需要进行抽离封装处理
- TS 类型推断写的时候需要格外注意一一对应,否则会报类型错误(一片红很不舒服)
index.tsx
const bindTags = async (data: IProdCategories) => {
try {
const { pasResult: tags } = await pluto.get(`/api/params/tagtree/${data.prodCatId}`);
const { pasResult: selectedTagIds } = await pluto.get(
`/api/front_category/product_tag/ids?category_id=${store.selectItem.categoryId}&prod_category_id=${data.prodCatId}`
);
openBindTagDialog(data.prodCatId, tags, selectedTagIds);
} catch (e) {
toast.error(e.message);
}
};
// 表格的一列
render: (data: IProdCategories) => <Link onClick={() => bindTags(data)}>设置</Link>
bind-pro-tag.tsx
import * as React from 'react';
import pluto from '@/common/libs/pluto';
import styled from 'styled-components';
import { Button, toast, Dialog, Checkbox, Result } from '@qunhe/muya-ui';
import { useStores } from '../../hooks/useStore';
import { IProduct, ITag } from '../../store/root';
import { observer } from 'mobx-react-lite';
import ReactDOM from 'react-dom';
const StyledDetailDiv = styled.div`
.dialog-title-right {
color: #a4a8ae;
font-size: 12px;
margin-left: 10px;
}
.tags-checkbox {
margin-right: 20px;
}
.dialog-hr {
height: 2px;
background-color: #f3f4f5;
border: none;
}
`;
interface IProps {
handleClose: () => void;
proCatId: number;
tags: IProduct[];
selectedTagIds: number[];
}
const BindProdTag: React.FunctionComponent<IProps> = observer(props => {
const store = useStores();
const { proCatId, tags } = props;
const [visibleBind, setVisibleBind] = React.useState<boolean>(true);
const [selectedTagIds, setSelectedTagIds] = React.useState<Array<Number>>([]);
React.useEffect(() => {
setSelectedTagIds(props.selectedTagIds);
}, [proCatId, tags, props.selectedTagIds]);
const handleBindClose = () => {
setVisibleBind(false);
};
const handleBindChange = (id: number) => {
let arr = Array.from(selectedTagIds);
const index = selectedTagIds.findIndex(item => item === id);
if (index !== -1) {
arr.splice(index, 1);
} else {
arr.push(id);
}
setSelectedTagIds(arr);
};
const onBindConfirm = () => {
return pluto
.post(`/api/front_category/product_tag/bind`, selectedTagIds, {
params: {
category_id: store.selectItem.categoryId,
prod_category_id: proCatId
}
})
.then(() => {
handleBindClose();
toast.success('保存成功!');
})
.catch(e => {
toast.error(e.message);
});
};
return (
<StyledDetailDiv>
<Dialog.Base
disablePortal
destroyOnClose={true}
open={visibleBind}
onClose={handleBindClose}
width={562}
height={400}
>
<Dialog.Title onClose={handleBindClose}>
<span>标签值绑定</span>
<span className="dialog-title-right">真分类关联的标签类型和标签值</span>
</Dialog.Title>
{tags.length ? (
<>
<Dialog.Content>
{tags.map((item: IProduct) => {
return (
<div key={item.localeId}>
<h5>{item.tagTypeName}</h5>
{item.productTags.map((items: ITag) => {
return (
<Checkbox
className="tags-checkbox"
key={items.tagId}
checked={selectedTagIds.includes(items.tagId)}
onChange={() => handleBindChange(items.tagId)}
>
<span>{items.tagName}</span>
</Checkbox>
);
})}
<hr className="dialog-hr" />
</div>
);
})}
</Dialog.Content>
<Dialog.Actions>
<Button onClick={handleBindClose}>取消</Button>
<Button htmlType="submit" type="primary" onClick={onBindConfirm}>
保存
</Button>
</Dialog.Actions>
</>
) : (
<Result type="empty" />
)}
</Dialog.Base>
</StyledDetailDiv>
);
});
const openBindTagDialog = (proCatId: number, tags: IProduct[], selectedTagIds: number[]) => {
const mountElement = document.createElement('div');
document.body.appendChild(mountElement);
const handleClose = () => {
ReactDOM.unmountComponentAtNode(mountElement);
document.body.removeChild(mountElement);
};
ReactDOM.render(
<BindProdTag
handleClose={handleClose}
proCatId={proCatId}
tags={tags}
selectedTagIds={selectedTagIds}
/>,
mountElement
);
};
export default openBindTagDialog;