UNPKG

2.38 kBJavaScriptView Raw
1import React, { useState, useEffect } from "react";
2import { Popover, Button, message } from "antd";
3import { CloseCircleOutlined, PlusCircleOutlined } from "@ant-design/icons";
4import { EditOutlined } from "@ant-design/icons";
5import styled from "styled-components";
6/**
7 * ----------------------------------------
8 * 弹窗多选列表
9 * @param {Array<{_id,name}>} datas
10 * @param {Array} value
11 * @param {Function} onChange
12 * @param {Boolean} [uniq = false] - 是否唯一
13 * ----------------------------------------
14 */
15export default function RolesChoose({
16 datas = [],
17 value = [],
18 onChange,
19 uniq = false,
20}) {
21 const [byId, setById] = useState({});
22
23 useEffect(() => {
24 setById(
25 datas.reduce((p, c) => {
26 p[c._id] = c;
27 return p;
28 }, {})
29 );
30 }, [datas]);
31
32 const onClickAdd = id => {
33 if (uniq && value.includes(id)) {
34 return message.info("已存在");
35 }
36 onChange([...value, id]);
37 };
38
39 const onClickRemove = removeId => {
40 onChange(value.filter(id => id !== removeId));
41 };
42
43 const Content = () => {
44 return (
45 <SBox>
46 {datas.map(item => (
47 <SItem key={item._id} onClick={() => onClickAdd(item._id)}>
48 <PlusCircleOutlined /> <span>{item.name}</span>
49 </SItem>
50 ))}
51 </SBox>
52 );
53 };
54
55 return (
56 <div>
57 <Popover content={Content} trigger="click">
58 <Button type="link" icon={<EditOutlined />}>
59 请选择
60 </Button>
61 </Popover>
62 <SRoles>
63 {(value || []).map((id, i) => (
64 <SRoleItem key={id + i} onClick={() => onClickRemove(id)}>
65 <SIndex>{i + 1}.</SIndex> {byId[id]?.name}
66 <span style={{ flex: 1 }} />
67 <CloseCircleOutlined />
68 </SRoleItem>
69 ))}
70 </SRoles>
71 </div>
72 );
73}
74
75const SBox = styled.div`
76 width: 300px;
77 height: 150px;
78 overflow: auto;
79`;
80
81const SItem = styled.div`
82 padding: 6px;
83 cursor: pointer;
84 &:active {
85 color: red;
86 }
87`;
88
89const SRoles = styled.div`
90 background-color: rgb(245, 245, 245);
91`;
92
93const SRoleItem = styled.div`
94 padding: 5px 10px;
95 cursor: pointer;
96 display: flex;
97 align-items: center;
98 border-bottom: 1px solid rgb(240, 240, 240);
99 user-select: none;
100 &:hover {
101 background-color: rgb(240, 240, 240);
102 }
103`;
104
105const SIndex = styled.div`
106 font-size: 15px;
107 margin-right: 7px;
108`;