index.tsx 7.2 KB

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