index.tsx 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. import {
  2. Badge,
  3. Button,
  4. Col,
  5. Empty,
  6. Input,
  7. Modal,
  8. Popconfirm,
  9. Row,
  10. Spin,
  11. Tooltip,
  12. Tree,
  13. } from 'antd';
  14. import { observer } from '@formily/react';
  15. import { service, state } from '..';
  16. import type { ActionType, ProColumns } from '@jetlinks/pro-table';
  17. import ProTable from '@jetlinks/pro-table';
  18. import { useEffect, useRef, useState } from 'react';
  19. import { history, useLocation } from 'umi';
  20. import { DisconnectOutlined, EditOutlined } from '@ant-design/icons';
  21. import BindUser from '../BindUser';
  22. import { onlyMessage } from '@/utils/util';
  23. const SyncUser = observer(() => {
  24. const [dept, setDept] = useState<string>();
  25. const location = useLocation<{ id: string }>();
  26. const id = (location as any).query?.id;
  27. const [visible, setVisible] = useState<boolean>(false);
  28. const [current, setCurrent] = useState<any>({});
  29. const [list, setList] = useState<any[]>([]);
  30. const idMap = {
  31. dingTalk: '钉钉',
  32. weixin: '微信',
  33. };
  34. const actionRef = useRef<ActionType>();
  35. const columns: ProColumns<any>[] = [
  36. {
  37. dataIndex: 'thirdPartyUserName',
  38. title: `${idMap[id]}用户名`,
  39. },
  40. {
  41. dataIndex: 'userId',
  42. title: `用户`,
  43. render: (text: any, record: any) => (
  44. <span>{record?.userId ? `${record?.userName}(${record?.username})` : ''}</span>
  45. ),
  46. },
  47. {
  48. dataIndex: 'status',
  49. title: '绑定状态',
  50. render: (text: any, record: any) => (
  51. <Badge
  52. status={record?.status === 1 ? 'success' : 'error'}
  53. text={record?.status === 1 ? '已绑定' : '未绑定'}
  54. />
  55. ),
  56. },
  57. {
  58. dataIndex: 'action',
  59. title: '操作',
  60. render: (text: any, record: any) => [
  61. <Tooltip title={'绑定用户'} key="bind">
  62. <Button
  63. type="link"
  64. onClick={() => {
  65. setCurrent(record);
  66. setVisible(true);
  67. }}
  68. >
  69. <EditOutlined />
  70. </Button>
  71. </Tooltip>,
  72. <Tooltip title={'解绑用户'} key="unbind">
  73. {record?.status === 1 && (
  74. <Button type="link">
  75. <Popconfirm
  76. title={'确认解绑'}
  77. onConfirm={async () => {
  78. if (record?.bindingId) {
  79. const resp = await service.syncUser.unBindUser(record.bindingId, {
  80. bindingId: record.bindingId,
  81. });
  82. if (resp.status === 200) {
  83. onlyMessage('操作成功!');
  84. actionRef.current?.reload();
  85. }
  86. }
  87. }}
  88. >
  89. <DisconnectOutlined />
  90. </Popconfirm>
  91. </Button>
  92. )}
  93. </Tooltip>,
  94. ],
  95. },
  96. ];
  97. const [treeData, setTreeData] = useState([]);
  98. const [loading, setLoading] = useState<boolean>(true);
  99. /**
  100. * 获取部门列表
  101. */
  102. const getDepartment = async (name?: string) => {
  103. if (state.current?.id) {
  104. if (id === 'dingTalk') {
  105. service.syncUser
  106. .dingTalkDept(state.current?.id)
  107. .then((resp) => {
  108. if (resp.status === 200) {
  109. let _data = resp.result;
  110. if (name) {
  111. _data = resp.result?.filter(
  112. (item: { id: string; name: string }) => item.name.indexOf(name) > -1,
  113. );
  114. }
  115. setTreeData(_data);
  116. setDept(resp.result[0].id);
  117. }
  118. })
  119. .finally(() => setLoading(false));
  120. } else if (id === 'weixin') {
  121. service.syncUser
  122. .wechatDept(state.current?.id)
  123. .then((resp) => {
  124. if (resp.status === 200) {
  125. let __data = resp.result;
  126. if (name) {
  127. __data = resp.result?.filter(
  128. (item: { id: string; name: string }) => item.name.indexOf(name) > -1,
  129. );
  130. }
  131. setTreeData(__data);
  132. setDept(resp.result[0].id);
  133. }
  134. })
  135. .finally(() => setLoading(false));
  136. }
  137. }
  138. };
  139. useEffect(() => {
  140. if (!state.current?.id) {
  141. history.goBack();
  142. }
  143. getDepartment();
  144. }, [id]);
  145. return (
  146. <Modal
  147. title="同步用户"
  148. bodyStyle={{ height: '600px', overflowY: 'auto' }}
  149. visible={true}
  150. footer={[
  151. <Button key="back" onClick={() => (state.syncUser = false)}>
  152. 关闭
  153. </Button>,
  154. ]}
  155. onCancel={() => (state.syncUser = false)}
  156. width="80vw"
  157. >
  158. <Spin spinning={loading}>
  159. <Row>
  160. <Col span={4}>
  161. <div style={{ borderRight: 'lightgray 1px solid', padding: '2px', height: '600px' }}>
  162. <Input.Search
  163. onSearch={(value) => getDepartment(value)}
  164. style={{ marginBottom: 8 }}
  165. placeholder="请输入部门名称"
  166. />
  167. {treeData && treeData.length !== 0 ? (
  168. <Tree
  169. fieldNames={{
  170. title: 'name',
  171. key: 'id',
  172. }}
  173. selectedKeys={[dept || '']}
  174. onSelect={(key) => {
  175. setDept(key[0] as string);
  176. }}
  177. treeData={treeData}
  178. />
  179. ) : (
  180. <Empty />
  181. )}
  182. </div>
  183. </Col>
  184. <Col span={20}>
  185. {dept ? (
  186. <ProTable
  187. rowKey="thirdPartyUserId"
  188. actionRef={actionRef}
  189. search={false}
  190. columns={columns}
  191. params={{ dept: dept }}
  192. request={(params) =>
  193. service
  194. .queryZipSyncUser(
  195. {
  196. dingTalk: 'dingtalk',
  197. weixin: 'wechat',
  198. }[id],
  199. id,
  200. state.current?.provider || '',
  201. state.current?.id || '',
  202. params.dept || '',
  203. )
  204. .then((resp: any) => {
  205. setList(resp);
  206. return {
  207. code: '',
  208. result: {
  209. data: resp || [],
  210. pageIndex: 0,
  211. pageSize: 0,
  212. total: 0,
  213. },
  214. status: 200,
  215. };
  216. })
  217. }
  218. headerTitle={
  219. <Button
  220. type="primary"
  221. onClick={async () => {
  222. const arr = list
  223. .filter((item) => item.status === 0)
  224. .map((i) => {
  225. return {
  226. userId: i.userId,
  227. providerName: i.userName,
  228. thirdPartyUserId: i.thirdPartyUserId,
  229. };
  230. });
  231. const resp = await service.syncUser.bindUser(
  232. id,
  233. state.current?.provider || '',
  234. state.current?.id || '',
  235. [...arr],
  236. );
  237. if (resp.status === 200) {
  238. onlyMessage('操作成功!');
  239. actionRef.current?.reload();
  240. }
  241. }}
  242. >
  243. 自动绑定
  244. </Button>
  245. }
  246. />
  247. ) : (
  248. <Empty />
  249. )}
  250. </Col>
  251. </Row>
  252. {visible && (
  253. <BindUser
  254. id={id}
  255. close={() => {
  256. setCurrent({});
  257. setVisible(false);
  258. }}
  259. data={current}
  260. reload={() => {
  261. setCurrent({});
  262. setVisible(false);
  263. actionRef.current?.reload();
  264. }}
  265. />
  266. )}
  267. </Spin>
  268. </Modal>
  269. );
  270. });
  271. export default SyncUser;