index.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. import { PageContainer } from '@ant-design/pro-layout';
  2. import {
  3. Avatar,
  4. Button,
  5. Card,
  6. Col,
  7. Descriptions,
  8. Divider,
  9. message,
  10. Popconfirm,
  11. Row,
  12. Upload,
  13. } from 'antd';
  14. import { useEffect, useState } from 'react';
  15. import styles from './index.less';
  16. import { UploadProps } from 'antd/lib/upload';
  17. import Token from '@/utils/token';
  18. import SystemConst from '@/utils/const';
  19. import { EditOutlined, LockOutlined, UploadOutlined, UserOutlined } from '@ant-design/icons';
  20. import InfoEdit from './edit/infoEdit';
  21. import PasswordEdit from './edit/passwordEdit';
  22. import Service from '@/pages/account/Center/service';
  23. import moment from 'moment';
  24. import { useModel } from 'umi';
  25. import usePermissions from '@/hooks/permission';
  26. import { Ellipsis, PermissionButton } from '@/components';
  27. import { isNoCommunity, onlyMessage } from '@/utils/util';
  28. import AccountInit from '@/pages/home/init/accountInit';
  29. export const service = new Service();
  30. const Center = () => {
  31. const { initialState, setInitialState } = useModel('@@initialState');
  32. const { permission: userPermission } = usePermissions('system/User');
  33. const [data, setData] = useState<any>();
  34. const [imageUrl, setImageUrl] = useState<string>('');
  35. const [infos, setInfos] = useState<boolean>(false);
  36. const [password, setPassword] = useState<boolean>(false);
  37. const [bindList, setBindList] = useState<any>([]);
  38. const [apiUser, setApiUser] = useState<any>();
  39. const iconMap = new Map();
  40. iconMap.set('dingtalk-ent-app', require('/public/images/notice/dingtalk.png'));
  41. iconMap.set('wechat-webapp', require('/public/images/notice/wechat.png'));
  42. iconMap.set('internal-standalone', require('/public/images/apply/provider1.png'));
  43. iconMap.set('third-party', require('/public/images/apply/provider5.png'));
  44. // const nameMap = new Map();
  45. // nameMap.set('dingtalk-ent-app', '钉钉');
  46. // nameMap.set('wechat-webapp', '微信');
  47. const bGroundMap = new Map();
  48. bGroundMap.set('dingtalk-ent-app', require('/public/images/notice/dingtalk-background.png'));
  49. bGroundMap.set('wechat-webapp', require('/public/images/notice/wechat-background.png'));
  50. const getDetail = () => {
  51. service.getUserDetail().subscribe((res) => {
  52. setData(res.result);
  53. setImageUrl(res.result.avatar);
  54. });
  55. };
  56. const getApiUser = async () => {
  57. const res = await service.queryCurrent();
  58. if (res.status === 200) {
  59. const isApiUser = res.result.dimensions.find(
  60. (item: any) => item.type === 'api-client' || item.type.id === 'api-client',
  61. );
  62. setApiUser(isApiUser);
  63. }
  64. };
  65. const uploadProps: UploadProps = {
  66. showUploadList: false,
  67. accept: 'image/jpeg,image/png',
  68. action: `/${SystemConst.API_BASE}/file/static`,
  69. headers: {
  70. 'X-Access-Token': Token.get(),
  71. },
  72. beforeUpload(file) {
  73. const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
  74. if (!isJpgOrPng) {
  75. message.error('请上传.png.jpg格式的文件');
  76. }
  77. const isSize = file.size / 1024 / 1024 < 4;
  78. if (!isSize) {
  79. message.error(`图片大小必须小于4M`);
  80. }
  81. return isJpgOrPng && isSize;
  82. },
  83. onChange(info) {
  84. if (info.file.status === 'uploading') {
  85. // setLoading(true);
  86. }
  87. if (info.file.status === 'done') {
  88. setImageUrl(info.file.response.result);
  89. service
  90. .saveUserDetail({
  91. name: data.name,
  92. avatar: info.file.response.result,
  93. })
  94. .subscribe((res) => {
  95. if (res.status === 200) {
  96. setImageUrl(info.file.response.result);
  97. getDetail();
  98. onlyMessage('上传成功');
  99. }
  100. });
  101. // setLoading(false);
  102. }
  103. },
  104. };
  105. const saveInfo = (parms: UserDetail) => {
  106. service.saveUserDetail(parms).subscribe((res) => {
  107. if (res.status === 200) {
  108. onlyMessage('保存成功');
  109. getDetail();
  110. setInfos(false);
  111. } else {
  112. onlyMessage('保存失败', 'error');
  113. }
  114. });
  115. };
  116. const savePassword = (parms: { oldPassword: string; newPassword: string }) => {
  117. service.savePassWord(parms).subscribe((res) => {
  118. if (res.status === 200) {
  119. onlyMessage('保存成功');
  120. setPassword(false);
  121. }
  122. });
  123. };
  124. const getBindInfo = () => {
  125. service.getSsoBinds().then((res) => {
  126. if (res.status === 200) {
  127. setBindList(res.result);
  128. }
  129. });
  130. };
  131. const unBind = (appId: string) => {
  132. service.unbind(appId).then((res) => {
  133. if (res.status === 200) {
  134. onlyMessage('解绑成功');
  135. getBindInfo();
  136. }
  137. });
  138. };
  139. useEffect(() => {
  140. getDetail();
  141. getApiUser();
  142. if (isNoCommunity) {
  143. getBindInfo();
  144. }
  145. }, []);
  146. useEffect(() => {
  147. if (data?.name) {
  148. const item = {
  149. ...initialState?.currentUser?.user,
  150. name: data.name,
  151. avatar: data.avatar,
  152. };
  153. setInitialState({
  154. ...initialState,
  155. currentUser: {
  156. ...initialState?.currentUser,
  157. user: item,
  158. },
  159. });
  160. }
  161. }, [data]);
  162. return (
  163. <PageContainer>
  164. <Card>
  165. <div className={styles.top}>
  166. <div className={styles.avatar}>
  167. <div>
  168. {data?.avatar ? (
  169. <Avatar size={140} src={imageUrl} />
  170. ) : (
  171. <Avatar size={140} icon={<UserOutlined />} />
  172. )}
  173. </div>
  174. <Upload {...uploadProps}>
  175. <Button>
  176. <UploadOutlined />
  177. 更换头像
  178. </Button>
  179. </Upload>
  180. </div>
  181. <div className={styles.content}>
  182. <Descriptions column={4} layout="vertical" labelStyle={{ fontWeight: 600 }}>
  183. <Descriptions.Item label="登录账号">{data?.username}</Descriptions.Item>
  184. <Descriptions.Item label="账号ID">
  185. <Ellipsis title={data?.id} tooltip={{ placement: 'topLeft' }} maxWidth={'90%'} />
  186. </Descriptions.Item>
  187. <Descriptions.Item label="注册时间">
  188. {moment(data?.createTime).format('YYYY-MM-DD HH:mm:ss')}
  189. </Descriptions.Item>
  190. <Descriptions.Item label="电话">{data?.telephone || '-'}</Descriptions.Item>
  191. <Descriptions.Item label="姓名">{data?.name}</Descriptions.Item>
  192. <Descriptions.Item label="角色">{data?.roleList[0]?.name || '-'}</Descriptions.Item>
  193. <Descriptions.Item label="组织">{data?.orgList[0]?.name || '-'}</Descriptions.Item>
  194. <Descriptions.Item label="邮箱">{data?.email || '-'}</Descriptions.Item>
  195. </Descriptions>
  196. </div>
  197. <a>
  198. <EditOutlined
  199. className={styles.action}
  200. onClick={() => {
  201. setInfos(true);
  202. }}
  203. />
  204. </a>
  205. </div>
  206. </Card>
  207. <Card
  208. className={styles.info}
  209. title={
  210. <div style={{ fontSize: '22px' }}>
  211. <Divider type="vertical" style={{ backgroundColor: '#2F54EB', width: 3 }} />
  212. 修改密码
  213. </div>
  214. }
  215. extra={
  216. <>
  217. <PermissionButton
  218. type="link"
  219. key="password"
  220. style={{ padding: 0 }}
  221. tooltip={{
  222. title: '重置密码',
  223. }}
  224. onClick={() => {
  225. setPassword(true);
  226. }}
  227. isPermission={userPermission.update}
  228. >
  229. <EditOutlined />
  230. </PermissionButton>
  231. </>
  232. }
  233. >
  234. <div style={{ display: 'flex', alignItems: 'flex-end' }}>
  235. <div>
  236. <LockOutlined
  237. style={{
  238. color: '#1d39c4',
  239. fontSize: '70px',
  240. }}
  241. />
  242. </div>
  243. <div style={{ marginLeft: 5, color: 'rgba(0, 0, 0, 0.55)' }}>
  244. 安全性高的密码可以使帐号更安全。建议您定期更换密码,设置一个包含字母,符号或数字中至少两项且长度超过8位的密码
  245. </div>
  246. </div>
  247. </Card>
  248. {isNoCommunity && (
  249. <Card
  250. className={styles.info}
  251. title={
  252. <div style={{ fontSize: '22px' }}>
  253. <Divider type="vertical" style={{ backgroundColor: '#2F54EB', width: 3 }} />
  254. 绑定三方账号
  255. </div>
  256. }
  257. >
  258. <Row gutter={[24, 24]}>
  259. {bindList.map((item: any) => (
  260. <Col key={item.id}>
  261. <Card
  262. style={{
  263. background: `url(${
  264. bGroundMap.get(item.provider) ||
  265. require('/public/images/notice/dingtalk-background.png')
  266. }) no-repeat`,
  267. backgroundSize: '100% 100%',
  268. width: 415,
  269. }}
  270. >
  271. <div className={styles.bind}>
  272. <div>
  273. <img style={{ height: 56 }} src={iconMap.get(item.provider)} />
  274. </div>
  275. <div>
  276. {item.bound ? (
  277. <div>
  278. <div style={{ fontSize: '22px' }}>绑定名:{item.others.name}</div>
  279. <div
  280. style={{
  281. fontSize: '14px',
  282. lineHeight: '20px',
  283. marginTop: '5px',
  284. color: '#00000073',
  285. }}
  286. >
  287. 绑定时间: {moment(item.bindTime).format('YYYY-MM-DD HH:mm:ss')}
  288. </div>
  289. </div>
  290. ) : (
  291. <div style={{ fontSize: '22px', width: 150 }}>
  292. <Ellipsis title={`${item.name}未绑定`} />
  293. </div>
  294. )}
  295. </div>
  296. <div>
  297. {item.bound ? (
  298. <Popconfirm
  299. title="确认解除绑定嘛?"
  300. onConfirm={() => {
  301. unBind(item.id);
  302. }}
  303. >
  304. <Button>解除绑定</Button>
  305. </Popconfirm>
  306. ) : (
  307. <Button
  308. type="primary"
  309. onClick={() => {
  310. window.open(
  311. `/${SystemConst.API_BASE}/application/sso/${item.id}/login?autoCreateUser=false`,
  312. );
  313. // window.open(`/#/account/center/bind`);
  314. localStorage.setItem('onBind', 'false');
  315. localStorage.setItem('onLogin', 'yes');
  316. window.onstorage = (e) => {
  317. if (e.newValue) {
  318. getBindInfo();
  319. }
  320. };
  321. }}
  322. >
  323. 立即绑定
  324. </Button>
  325. )}
  326. </div>
  327. </div>
  328. </Card>
  329. </Col>
  330. ))}
  331. </Row>
  332. </Card>
  333. )}
  334. {!apiUser && (
  335. <Card
  336. style={{ marginTop: 15 }}
  337. title={
  338. <div style={{ fontSize: '22px' }}>
  339. <Divider type="vertical" style={{ backgroundColor: '#2F54EB', width: 3 }} />
  340. 首页视图
  341. </div>
  342. }
  343. >
  344. <AccountInit />,
  345. </Card>
  346. )}
  347. {infos && (
  348. <InfoEdit
  349. data={data}
  350. save={(item: any) => {
  351. saveInfo(item);
  352. }}
  353. close={() => {
  354. setInfos(false);
  355. }}
  356. />
  357. )}
  358. {password && (
  359. <PasswordEdit
  360. save={(item: any) => {
  361. savePassword(item);
  362. }}
  363. visible={password}
  364. close={() => {
  365. setPassword(false);
  366. }}
  367. />
  368. )}
  369. </PageContainer>
  370. );
  371. };
  372. export default Center;