@hzab/group-user-selector 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/README.md +67 -0
- package/package.json +52 -0
- package/src/GroupSelection/index.jsx +250 -0
- package/src/GroupSelection/index.less +160 -0
- package/src/assets/imgs/defaultAvatar.png +0 -0
- package/src/assets/imgs/department.png +0 -0
- package/src/index.tsx +5 -0
package/CHANGELOG.md
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# @hzab/group-user-selector
|
|
2
|
+
|
|
3
|
+
组件模板
|
|
4
|
+
|
|
5
|
+
- node@16.16.0
|
|
6
|
+
|
|
7
|
+
- 注意:首次克隆先执行 npm run prepare 命令
|
|
8
|
+
|
|
9
|
+
# 组件
|
|
10
|
+
|
|
11
|
+
## 示例
|
|
12
|
+
|
|
13
|
+
```jsx
|
|
14
|
+
import Demo from "@hzab/group-user-selector";
|
|
15
|
+
|
|
16
|
+
<Demo />;
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## API
|
|
20
|
+
|
|
21
|
+
### InfoPanel Attributes
|
|
22
|
+
|
|
23
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
24
|
+
| ------ | ------ | ---- | ------ | ----------------- |
|
|
25
|
+
| schema | Object | 是 | - | 数据信息的 schema |
|
|
26
|
+
|
|
27
|
+
# 组件开发流程
|
|
28
|
+
|
|
29
|
+
- 在 config/webpack.config.js 中按需修改 library 配置的文件名
|
|
30
|
+
- 在 config/webpack.config.js 中按需修改 alias 配置的包名,便于本地调试
|
|
31
|
+
- 在 tsconfig.json 中按需修改 paths 配置的包名,解决 ts 报错问题
|
|
32
|
+
- npm run dev
|
|
33
|
+
|
|
34
|
+
## 文件目录
|
|
35
|
+
|
|
36
|
+
- example 本地开发测试代码
|
|
37
|
+
- src 组件源码
|
|
38
|
+
|
|
39
|
+
## 命令
|
|
40
|
+
|
|
41
|
+
- Mac 执行该命令,设置 pre-commit 为可执行文件
|
|
42
|
+
|
|
43
|
+
- npm run mac-chmod
|
|
44
|
+
- chmod +x .husky && chmod +x .husky/pre-commit
|
|
45
|
+
|
|
46
|
+
- 生成文档:npm run docs
|
|
47
|
+
- 本地运行:npm run dev
|
|
48
|
+
- 打包编译:npm run build
|
|
49
|
+
|
|
50
|
+
## 发布
|
|
51
|
+
|
|
52
|
+
- 注意:示例代码生效,但发布之后未生效。确认是否执行了编译!!!
|
|
53
|
+
|
|
54
|
+
- 编译组件:npm run build
|
|
55
|
+
- 命令:npm publish --access public
|
|
56
|
+
- 发布目录:
|
|
57
|
+
- src
|
|
58
|
+
|
|
59
|
+
## 配置
|
|
60
|
+
|
|
61
|
+
### 配置文件
|
|
62
|
+
|
|
63
|
+
- 本地配置文件:config/config.js
|
|
64
|
+
|
|
65
|
+
### webpack 配置文件
|
|
66
|
+
|
|
67
|
+
- config/webpack.config.js
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hzab/group-user-selector",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "src",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "webpack serve -c ./config/webpack.config.js --env local",
|
|
8
|
+
"build": "webpack -c ./config/webpack.config.js --env production",
|
|
9
|
+
"publish-patch": "npm version patch && npm publish --access public",
|
|
10
|
+
"publish-minor": "npm version minor && npm publish --access public",
|
|
11
|
+
"publish-major": "npm version major && npm publish --access public",
|
|
12
|
+
"prepare": "husky install",
|
|
13
|
+
"mac-chmod": "chmod +x .husky && chmod +x .husky/pre-commit",
|
|
14
|
+
"docs": "typedoc"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"src",
|
|
18
|
+
"CHANGELOG.md"
|
|
19
|
+
],
|
|
20
|
+
"keywords": [],
|
|
21
|
+
"author": "CaiYansong",
|
|
22
|
+
"license": "ISC",
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@hzab/permissions": "^1.0.0",
|
|
25
|
+
"@hzab/webpack-config": "^1.0.0",
|
|
26
|
+
"@types/react": "^17.0.62",
|
|
27
|
+
"@types/react-dom": "^17.0.20",
|
|
28
|
+
"antd": "^4.14.0",
|
|
29
|
+
"axios": "^1.4.0",
|
|
30
|
+
"eslint": "^8.30.0",
|
|
31
|
+
"less": "^4.1.3",
|
|
32
|
+
"mobx": "^6.7.0",
|
|
33
|
+
"mobx-react": "^7.6.0",
|
|
34
|
+
"react": "^17.0.2",
|
|
35
|
+
"react-dom": "^17.0.2",
|
|
36
|
+
"react-router-dom": "^6.14.1",
|
|
37
|
+
"typedoc": "^0.24.8",
|
|
38
|
+
"typescript": "^4.9.4"
|
|
39
|
+
},
|
|
40
|
+
"directories": {
|
|
41
|
+
"src": "src"
|
|
42
|
+
},
|
|
43
|
+
"lint-staged": {
|
|
44
|
+
"**.{js,jsx,ts,tsx,css,scss,less,json,html}": [
|
|
45
|
+
"prettier --write"
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@hzab/data-model": "^1.7.0",
|
|
50
|
+
"lodash": "^4.17.21"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { useEffect, useState, useImperativeHandle, forwardRef } from "react";
|
|
2
|
+
import { Input, Breadcrumb, Checkbox, message, Spin, Pagination, ConfigProvider } from "antd";
|
|
3
|
+
import zhCN from 'antd/es/locale/zh_CN';
|
|
4
|
+
import { CloseCircleFilled, SearchOutlined } from "@ant-design/icons";
|
|
5
|
+
import 'moment/locale/zh-cn';
|
|
6
|
+
import _ from "lodash";
|
|
7
|
+
import defaultAvatar from "../assets/imgs/defaultAvatar.png";
|
|
8
|
+
import department from "../assets/imgs/department.png";
|
|
9
|
+
|
|
10
|
+
import "./index.less";
|
|
11
|
+
|
|
12
|
+
function GroupSelection(props, ref) {
|
|
13
|
+
const {
|
|
14
|
+
model,
|
|
15
|
+
searchModel,
|
|
16
|
+
queryKey = "parentId",
|
|
17
|
+
searchQueryKey = "search",
|
|
18
|
+
value = [],
|
|
19
|
+
labelKey = "label",
|
|
20
|
+
valueKey = "value",
|
|
21
|
+
isUserKey = "isUser",
|
|
22
|
+
imgKey = "img",
|
|
23
|
+
hasPagination = true,
|
|
24
|
+
hasSearch = true
|
|
25
|
+
} = props;
|
|
26
|
+
const [breadcrumb, setBreadcrumb] = useState([
|
|
27
|
+
{
|
|
28
|
+
[labelKey]: "首页",
|
|
29
|
+
[valueKey]: undefined,
|
|
30
|
+
},
|
|
31
|
+
]);
|
|
32
|
+
const [loading, setLoading] = useState(false);
|
|
33
|
+
const [checkAll, setCheckAll] = useState(false);
|
|
34
|
+
const [selectList, setSelectList] = useState([]);
|
|
35
|
+
const [selectedList, setSelectedList] = useState([...value]);
|
|
36
|
+
const [search, setSearch] = useState("");
|
|
37
|
+
const [searchList, setSearchList] = useState([]);
|
|
38
|
+
const [total, setTotal] = useState(0);
|
|
39
|
+
const [pageData, setPageData] = useState(hasPagination ? {
|
|
40
|
+
pageSize: 10,
|
|
41
|
+
pageNum: 1
|
|
42
|
+
} : {});
|
|
43
|
+
|
|
44
|
+
// 通过useImperativeHandle定义要抛出的值或方法
|
|
45
|
+
useImperativeHandle(ref, () => ({
|
|
46
|
+
selectedList,
|
|
47
|
+
}));
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
const selectedValues = new Set(selectedList.map((item) => item[valueKey]));
|
|
51
|
+
const isAllSelected = selectList.every((item) => selectedValues.has(item[valueKey]));
|
|
52
|
+
setCheckAll(isAllSelected);
|
|
53
|
+
}, [selectList, selectedList]);
|
|
54
|
+
|
|
55
|
+
const getTreeData = (value) => {
|
|
56
|
+
setLoading(true);
|
|
57
|
+
model &&
|
|
58
|
+
model.get({ [queryKey]: value }).then((res) => {
|
|
59
|
+
setSelectList(res);
|
|
60
|
+
})
|
|
61
|
+
.catch((err) => {
|
|
62
|
+
message.error(err._message || "未知错误");
|
|
63
|
+
})
|
|
64
|
+
.finally(() => {
|
|
65
|
+
setLoading(false);
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
getTreeData();
|
|
72
|
+
}, []);
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
const handleSearch = (data) => {
|
|
76
|
+
setLoading(true);
|
|
77
|
+
searchModel &&
|
|
78
|
+
searchModel.get({ ...data }).then((res) => {
|
|
79
|
+
const list = res?.list || [];
|
|
80
|
+
setSearchList(list);
|
|
81
|
+
setTotal(res?.total);
|
|
82
|
+
}).catch((err) => {
|
|
83
|
+
message.error(err._message || "未知错误");
|
|
84
|
+
})
|
|
85
|
+
.finally(() => {
|
|
86
|
+
setLoading(false);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const handleChangePage = (pageNum, pageSize) => {
|
|
91
|
+
const pages = {
|
|
92
|
+
pageNum: pageSize !== pageData?.pageSize ? 1 : pageNum,
|
|
93
|
+
pageSize
|
|
94
|
+
}
|
|
95
|
+
setPageData({
|
|
96
|
+
...pages
|
|
97
|
+
})
|
|
98
|
+
handleSearch({
|
|
99
|
+
[searchQueryKey]: search,
|
|
100
|
+
...pages
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const onSearch = (value) => {
|
|
105
|
+
|
|
106
|
+
setSearch(value);
|
|
107
|
+
if (!value) return;
|
|
108
|
+
handleSearch({
|
|
109
|
+
[searchQueryKey]: value,
|
|
110
|
+
...pageData
|
|
111
|
+
})
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const handleBreadcrumb = (e) => {
|
|
115
|
+
const index = breadcrumb.findIndex((item) => item[valueKey] === e[valueKey]);
|
|
116
|
+
const arr = [...breadcrumb];
|
|
117
|
+
arr.splice(index + 1);
|
|
118
|
+
setBreadcrumb(arr);
|
|
119
|
+
getTreeData(e[valueKey]);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const handleClickItem = (item) => {
|
|
123
|
+
const arr = [...breadcrumb];
|
|
124
|
+
arr.push(item);
|
|
125
|
+
setBreadcrumb(arr);
|
|
126
|
+
|
|
127
|
+
getTreeData(item[valueKey]);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const handleCheckDelete = (item) => {
|
|
131
|
+
setSelectedList(selectedList.filter((i) => i[valueKey] !== item[valueKey]));
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const handleCheckItem = (item) => {
|
|
135
|
+
const is = selectedList.some((i) => i[valueKey] === item[valueKey]);
|
|
136
|
+
if (is) {
|
|
137
|
+
handleCheckDelete(item);
|
|
138
|
+
} else {
|
|
139
|
+
setSelectedList([...selectedList, item]);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const handleCheckAll = (e) => {
|
|
144
|
+
const isChecked = e.target.checked;
|
|
145
|
+
if (isChecked) {
|
|
146
|
+
// 全选:合并 selectList 并去重(基于 value)
|
|
147
|
+
setSelectedList((prev) => {
|
|
148
|
+
const selectedValues = new Set(prev.map((item) => item[valueKey])); // 已选值的 Set
|
|
149
|
+
const newItems = selectList.filter((item) => !selectedValues.has(item[valueKey]));
|
|
150
|
+
return [...prev, ...newItems]; // 合并新项
|
|
151
|
+
});
|
|
152
|
+
} else {
|
|
153
|
+
// 取消全选:仅移除 selectList 中的项(基于 value)
|
|
154
|
+
setSelectedList((prev) => {
|
|
155
|
+
const selectValues = new Set(selectList.map((item) => item[valueKey])); // 需移除值的 Set
|
|
156
|
+
return prev.filter((item) => !selectValues.has(item[valueKey])); // 过滤保留其他项
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const handleCheck = (item) => {
|
|
162
|
+
const is = selectedList.some((i) => i[valueKey] === item[valueKey]);
|
|
163
|
+
return is;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const ItemRenter = (item) => {
|
|
167
|
+
const isCheck = handleCheck(item);
|
|
168
|
+
return (
|
|
169
|
+
<div className="group-selection-list-item" key={item[valueKey]}>
|
|
170
|
+
<div className="avatar" onClick={() => handleCheckItem(item)}>
|
|
171
|
+
<Checkbox checked={isCheck} />
|
|
172
|
+
<img src={item[imgKey] ? item[imgKey] : item[isUserKey] ? defaultAvatar : department} />
|
|
173
|
+
<div className="label">{item[labelKey]}</div>
|
|
174
|
+
</div>
|
|
175
|
+
{item[isUserKey] ? null : <div
|
|
176
|
+
className={`next ${isCheck ? "noNext" : ""}`}
|
|
177
|
+
onClick={() => {
|
|
178
|
+
if (isCheck) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
handleClickItem(item);
|
|
182
|
+
}}
|
|
183
|
+
>
|
|
184
|
+
下级
|
|
185
|
+
</div>}
|
|
186
|
+
</div>
|
|
187
|
+
);
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
return (
|
|
191
|
+
<ConfigProvider locale={zhCN}>
|
|
192
|
+
|
|
193
|
+
<div className="group-selection">
|
|
194
|
+
{loading ? <div className="group-selection-loading">
|
|
195
|
+
<Spin tip="Loading..." spinning={loading} />
|
|
196
|
+
</div> : null}
|
|
197
|
+
<div className="group-selection-list">
|
|
198
|
+
{hasSearch ? <Input.Search onSearch={onSearch} enterButton placeholder="搜索成员" allowClear /> : null}
|
|
199
|
+
|
|
200
|
+
{/* <Input addonBefore={<SearchOutlined />} allowClear placeholder="搜索成员" onChange={onSearch} /> */}
|
|
201
|
+
{search ? (
|
|
202
|
+
<div className="group-selection-search-view">
|
|
203
|
+
<div className="group-selection-search-list">
|
|
204
|
+
{searchList.map((item, index) => {
|
|
205
|
+
return ItemRenter(item);
|
|
206
|
+
})}
|
|
207
|
+
</div>
|
|
208
|
+
|
|
209
|
+
{hasPagination ? <div className="group-selection-search-pagination">
|
|
210
|
+
<Pagination current={pageData?.pageNum} total={total} pageSize={pageData?.pageSize} onChange={handleChangePage} size="small" />
|
|
211
|
+
</div> : null}
|
|
212
|
+
</div>
|
|
213
|
+
) : null}
|
|
214
|
+
<Breadcrumb className="group-selection-breadcrumb">
|
|
215
|
+
{breadcrumb.map((item) => {
|
|
216
|
+
return (
|
|
217
|
+
<Breadcrumb.Item style={{ cursor: "pointer" }} onClick={() => handleBreadcrumb(item)} key={item[valueKey]}>
|
|
218
|
+
{item[labelKey]}
|
|
219
|
+
</Breadcrumb.Item>
|
|
220
|
+
);
|
|
221
|
+
})}
|
|
222
|
+
</Breadcrumb>
|
|
223
|
+
<div className="group-selection-list-check">
|
|
224
|
+
<Checkbox onChange={handleCheckAll} checked={checkAll && selectList.length} /> 全选
|
|
225
|
+
</div>
|
|
226
|
+
<div className="group-selection-list-view">
|
|
227
|
+
{selectList.map((item, index) => {
|
|
228
|
+
return ItemRenter(item);
|
|
229
|
+
})}
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
<div className="group-selection-detail">
|
|
233
|
+
<div className="group-selection-detail-list">
|
|
234
|
+
{selectedList.map((item, index) => {
|
|
235
|
+
return (
|
|
236
|
+
<div className="group-selection-detail-item" key={item[valueKey]}>
|
|
237
|
+
<img src={item[imgKey] ? item[imgKey] : item[isUserKey] ? defaultAvatar : department} />
|
|
238
|
+
<div className="label">{item[labelKey]}</div>
|
|
239
|
+
<CloseCircleFilled style={{ cursor: "pointer" }} onClick={() => handleCheckDelete(item)} />
|
|
240
|
+
</div>
|
|
241
|
+
);
|
|
242
|
+
})}
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
</div>
|
|
246
|
+
</ConfigProvider>
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export default forwardRef(GroupSelection);
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
.group-selection {
|
|
2
|
+
position: relative;
|
|
3
|
+
width: 100%;
|
|
4
|
+
height: 100%;
|
|
5
|
+
overflow: hidden;
|
|
6
|
+
display: grid;
|
|
7
|
+
grid-template-columns: 1fr 1fr;
|
|
8
|
+
|
|
9
|
+
.group-selection-loading {
|
|
10
|
+
position: absolute;
|
|
11
|
+
top: 0;
|
|
12
|
+
left: 0;
|
|
13
|
+
width: 100%;
|
|
14
|
+
height: 100%;
|
|
15
|
+
display: flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
justify-content: center;
|
|
18
|
+
background: rgba(255, 255, 255, 0.5);
|
|
19
|
+
z-index: 100;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.group-selection-list {
|
|
23
|
+
box-sizing: border-box;
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
position: relative;
|
|
27
|
+
height: 100%;
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
padding: 24px;
|
|
30
|
+
border-right: 1px solid #e8e8e8;
|
|
31
|
+
|
|
32
|
+
.group-selection-search-view {
|
|
33
|
+
display: flex;
|
|
34
|
+
flex-direction: column;
|
|
35
|
+
box-sizing: border-box;
|
|
36
|
+
position: absolute;
|
|
37
|
+
top: 56px;
|
|
38
|
+
left: 24px;
|
|
39
|
+
width: calc(100% - 48px);
|
|
40
|
+
height: calc(100% - 80px);
|
|
41
|
+
overflow-y: hidden;
|
|
42
|
+
z-index: 10;
|
|
43
|
+
background-color: #fff;
|
|
44
|
+
|
|
45
|
+
.group-selection-search-list {
|
|
46
|
+
box-sizing: border-box;
|
|
47
|
+
flex: 1;
|
|
48
|
+
overflow-y: auto;
|
|
49
|
+
padding: 24px ;
|
|
50
|
+
|
|
51
|
+
&::-webkit-scrollbar {
|
|
52
|
+
display: none;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.group-selection-search-pagination {
|
|
57
|
+
position: absolute;
|
|
58
|
+
left: 0;
|
|
59
|
+
bottom: 0;
|
|
60
|
+
width: 100%;
|
|
61
|
+
height: 40px;
|
|
62
|
+
display: flex;
|
|
63
|
+
align-items: center;
|
|
64
|
+
justify-content: center;
|
|
65
|
+
background-color: #fff;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.group-selection-breadcrumb {
|
|
70
|
+
margin-top: 12px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.group-selection-list-check {
|
|
74
|
+
margin: 12px 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.group-selection-list-view {
|
|
78
|
+
flex: 1;
|
|
79
|
+
overflow: auto;
|
|
80
|
+
|
|
81
|
+
&::-webkit-scrollbar {
|
|
82
|
+
display: none;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.group-selection-list-item {
|
|
87
|
+
display: flex;
|
|
88
|
+
align-items: center;
|
|
89
|
+
justify-content: space-between;
|
|
90
|
+
margin-bottom: 24px;
|
|
91
|
+
|
|
92
|
+
.avatar {
|
|
93
|
+
display: flex;
|
|
94
|
+
align-items: center;
|
|
95
|
+
cursor: pointer;
|
|
96
|
+
|
|
97
|
+
img {
|
|
98
|
+
width: 32px;
|
|
99
|
+
height: auto;
|
|
100
|
+
margin: 0 12px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.label {
|
|
104
|
+
font-size: 16px;
|
|
105
|
+
color: #141414;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.next {
|
|
110
|
+
color: rgb(64, 62, 245);
|
|
111
|
+
cursor: pointer;
|
|
112
|
+
flex-shrink: 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.noNext {
|
|
116
|
+
opacity: 0.5;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.group-selection-detail {
|
|
122
|
+
position: relative;
|
|
123
|
+
height: 100%;
|
|
124
|
+
overflow: auto;
|
|
125
|
+
|
|
126
|
+
&::-webkit-scrollbar {
|
|
127
|
+
display: none;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.group-selection-detail-list {
|
|
131
|
+
display: flex;
|
|
132
|
+
align-items: center;
|
|
133
|
+
flex-wrap: wrap;
|
|
134
|
+
padding: 24px;
|
|
135
|
+
|
|
136
|
+
.group-selection-detail-item {
|
|
137
|
+
flex-shrink: 0;
|
|
138
|
+
display: flex;
|
|
139
|
+
align-items: center;
|
|
140
|
+
padding: 4px 8px;
|
|
141
|
+
margin: 0 12px 12px 0;
|
|
142
|
+
color: #e8e8e8;
|
|
143
|
+
border-radius: 8px;
|
|
144
|
+
background-color: aliceblue;
|
|
145
|
+
|
|
146
|
+
img {
|
|
147
|
+
width: 32px;
|
|
148
|
+
height: auto;
|
|
149
|
+
margin-right: 12px;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.label {
|
|
153
|
+
font-size: 16px;
|
|
154
|
+
color: #141414;
|
|
155
|
+
margin-right: 12px;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
Binary file
|
|
Binary file
|