AddUser.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. import React, { useState } from 'react';
  2. import { API, isMobile, showError, showSuccess } from '../../helpers';
  3. import {
  4. Button,
  5. Input,
  6. SideSheet,
  7. Space,
  8. Spin,
  9. Typography,
  10. Card,
  11. Tag,
  12. Avatar
  13. } from '@douyinfe/semi-ui';
  14. import {
  15. IconUser,
  16. IconSave,
  17. IconClose,
  18. IconKey,
  19. IconUserAdd,
  20. IconEdit,
  21. } from '@douyinfe/semi-icons';
  22. import { useTranslation } from 'react-i18next';
  23. const { Text, Title } = Typography;
  24. const AddUser = (props) => {
  25. const { t } = useTranslation();
  26. const originInputs = {
  27. username: '',
  28. display_name: '',
  29. password: '',
  30. remark: '',
  31. };
  32. const [inputs, setInputs] = useState(originInputs);
  33. const [loading, setLoading] = useState(false);
  34. const { username, display_name, password, remark } = inputs;
  35. const handleInputChange = (name, value) => {
  36. setInputs((inputs) => ({ ...inputs, [name]: value }));
  37. };
  38. const submit = async () => {
  39. setLoading(true);
  40. if (inputs.username === '' || inputs.password === '') {
  41. setLoading(false);
  42. showError(t('用户名和密码不能为空!'));
  43. return;
  44. }
  45. const res = await API.post(`/api/user/`, inputs);
  46. const { success, message } = res.data;
  47. if (success) {
  48. showSuccess(t('用户账户创建成功!'));
  49. setInputs(originInputs);
  50. props.refresh();
  51. props.handleClose();
  52. } else {
  53. showError(message);
  54. }
  55. setLoading(false);
  56. };
  57. const handleCancel = () => {
  58. props.handleClose();
  59. };
  60. return (
  61. <>
  62. <SideSheet
  63. placement={'left'}
  64. title={
  65. <Space>
  66. <Tag color="green" shape="circle">{t('新建')}</Tag>
  67. <Title heading={4} className="m-0">
  68. {t('添加用户')}
  69. </Title>
  70. </Space>
  71. }
  72. headerStyle={{
  73. borderBottom: '1px solid var(--semi-color-border)',
  74. padding: '24px'
  75. }}
  76. bodyStyle={{ padding: '0' }}
  77. visible={props.visible}
  78. width={isMobile() ? '100%' : 600}
  79. footer={
  80. <div className="flex justify-end bg-white">
  81. <Space>
  82. <Button
  83. theme="solid"
  84. className="!rounded-full"
  85. onClick={submit}
  86. icon={<IconSave />}
  87. loading={loading}
  88. >
  89. {t('提交')}
  90. </Button>
  91. <Button
  92. theme="light"
  93. className="!rounded-full"
  94. type="primary"
  95. onClick={handleCancel}
  96. icon={<IconClose />}
  97. >
  98. {t('取消')}
  99. </Button>
  100. </Space>
  101. </div>
  102. }
  103. closeIcon={null}
  104. onCancel={() => handleCancel()}
  105. >
  106. <Spin spinning={loading}>
  107. <div className="p-6">
  108. <Card className="!rounded-2xl shadow-sm border-0">
  109. <div className="flex items-center mb-2">
  110. <Avatar size="small" color="blue" className="mr-2 shadow-md">
  111. <IconUserAdd size={16} />
  112. </Avatar>
  113. <div>
  114. <Text className="text-lg font-medium">{t('用户信息')}</Text>
  115. <div className="text-xs text-gray-600">{t('创建新用户账户')}</div>
  116. </div>
  117. </div>
  118. <div className="space-y-4">
  119. <div>
  120. <Text strong className="block mb-2">{t('用户名')}</Text>
  121. <Input
  122. placeholder={t('请输入用户名')}
  123. onChange={(value) => handleInputChange('username', value)}
  124. value={username}
  125. autoComplete="off"
  126. className="!rounded-lg"
  127. prefix={<IconUser />}
  128. showClear
  129. required
  130. />
  131. </div>
  132. <div>
  133. <Text strong className="block mb-2">{t('显示名称')}</Text>
  134. <Input
  135. placeholder={t('请输入显示名称')}
  136. onChange={(value) => handleInputChange('display_name', value)}
  137. value={display_name}
  138. autoComplete="off"
  139. className="!rounded-lg"
  140. prefix={<IconUser />}
  141. showClear
  142. />
  143. </div>
  144. <div>
  145. <Text strong className="block mb-2">{t('密码')}</Text>
  146. <Input
  147. type="password"
  148. placeholder={t('请输入密码')}
  149. onChange={(value) => handleInputChange('password', value)}
  150. value={password}
  151. autoComplete="off"
  152. className="!rounded-lg"
  153. prefix={<IconKey />}
  154. required
  155. />
  156. </div>
  157. <div>
  158. <Text strong className="block mb-2">{t('备注')}</Text>
  159. <Input
  160. placeholder={t('请输入备注(仅管理员可见)')}
  161. onChange={(value) => handleInputChange('remark', value)}
  162. value={remark}
  163. autoComplete="off"
  164. className="!rounded-lg"
  165. prefix={<IconEdit />}
  166. showClear
  167. />
  168. </div>
  169. </div>
  170. </Card>
  171. </div>
  172. </Spin>
  173. </SideSheet>
  174. </>
  175. );
  176. };
  177. export default AddUser;