EditToken.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. import React, {useEffect, useRef, useState} from 'react';
  2. // import {Button, Form, Header, Message, Segment} from 'semantic-ui-react';
  3. import {useParams, useNavigate} from 'react-router-dom';
  4. import {API, isMobile, showError, showSuccess, timestamp2string} from '../../helpers';
  5. import {renderQuota, renderQuotaWithPrompt} from '../../helpers/render';
  6. import {Layout, SideSheet, Button, Space, Spin, Banner, Input, DatePicker, AutoComplete, Typography} from "@douyinfe/semi-ui";
  7. import Title from "@douyinfe/semi-ui/lib/es/typography/title";
  8. import {Divider} from "semantic-ui-react";
  9. const EditToken = (props) => {
  10. const isEdit = props.editingToken.id !== undefined;
  11. const [loading, setLoading] = useState(isEdit);
  12. const originInputs = {
  13. name: '',
  14. remain_quota: isEdit ? 0 : 500000,
  15. expired_time: -1,
  16. unlimited_quota: false
  17. };
  18. const [inputs, setInputs] = useState(originInputs);
  19. const {name, remain_quota, expired_time, unlimited_quota} = inputs;
  20. // const [visible, setVisible] = useState(false);
  21. const navigate = useNavigate();
  22. const handleInputChange = (name, value) => {
  23. setInputs((inputs) => ({...inputs, [name]: value}));
  24. };
  25. const handleCancel = () => {
  26. props.handleClose();
  27. }
  28. const setExpiredTime = (month, day, hour, minute) => {
  29. let now = new Date();
  30. let timestamp = now.getTime() / 1000;
  31. let seconds = month * 30 * 24 * 60 * 60;
  32. seconds += day * 24 * 60 * 60;
  33. seconds += hour * 60 * 60;
  34. seconds += minute * 60;
  35. if (seconds !== 0) {
  36. timestamp += seconds;
  37. setInputs({...inputs, expired_time: timestamp2string(timestamp)});
  38. } else {
  39. setInputs({...inputs, expired_time: -1});
  40. }
  41. };
  42. const setUnlimitedQuota = () => {
  43. setInputs({...inputs, unlimited_quota: !unlimited_quota});
  44. };
  45. const loadToken = async () => {
  46. setLoading(true);
  47. let res = await API.get(`/api/token/${props.editingToken.id}`);
  48. const {success, message, data} = res.data;
  49. if (success) {
  50. if (data.expired_time !== -1) {
  51. data.expired_time = timestamp2string(data.expired_time);
  52. }
  53. setInputs(data);
  54. } else {
  55. showError(message);
  56. }
  57. setLoading(false);
  58. };
  59. useEffect(() => {
  60. if (isEdit) {
  61. loadToken().then(
  62. () => {
  63. console.log(inputs);
  64. }
  65. );
  66. } else {
  67. setInputs(originInputs);
  68. }
  69. }, [props.editingToken.id]);
  70. const submit = async () => {
  71. setLoading(true);
  72. if (!isEdit && inputs.name === '') return;
  73. let localInputs = inputs;
  74. localInputs.remain_quota = parseInt(localInputs.remain_quota);
  75. if (localInputs.expired_time !== -1) {
  76. let time = Date.parse(localInputs.expired_time);
  77. if (isNaN(time)) {
  78. showError('过期时间格式错误!');
  79. return;
  80. }
  81. localInputs.expired_time = Math.ceil(time / 1000);
  82. }
  83. let res;
  84. if (isEdit) {
  85. res = await API.put(`/api/token/`, {...localInputs, id: parseInt(props.editingToken.id)});
  86. } else {
  87. res = await API.post(`/api/token/`, localInputs);
  88. }
  89. const {success, message} = res.data;
  90. if (success) {
  91. if (isEdit) {
  92. showSuccess('令牌更新成功!');
  93. props.refresh();
  94. props.handleClose();
  95. } else {
  96. showSuccess('令牌创建成功,请在列表页面点击复制获取令牌!');
  97. setInputs(originInputs);
  98. props.refresh();
  99. props.handleClose();
  100. }
  101. } else {
  102. showError(message);
  103. }
  104. setLoading(false);
  105. };
  106. return (
  107. <>
  108. <SideSheet
  109. title={<Title level={3}>{isEdit ? '更新令牌信息' : '创建新的令牌'}</Title>}
  110. headerStyle={{borderBottom: '1px solid var(--semi-color-border)'}}
  111. bodyStyle={{borderBottom: '1px solid var(--semi-color-border)'}}
  112. visible={props.visiable}
  113. footer={
  114. <div style={{display: 'flex', justifyContent: 'flex-end'}}>
  115. <Space>
  116. <Button theme='solid' size={'large'} onClick={submit}>提交</Button>
  117. <Button theme='solid' size={'large'} type={'tertiary'} onClick={handleCancel}>取消</Button>
  118. </Space>
  119. </div>
  120. }
  121. closeIcon={null}
  122. onCancel={() => handleCancel()}
  123. width={isMobile() ? '100%' : 600}
  124. >
  125. <Spin spinning={loading}>
  126. <Input
  127. style={{ marginTop: 20 }}
  128. label='名称'
  129. name='name'
  130. placeholder={'请输入名称'}
  131. onChange={(value) => handleInputChange('name', value)}
  132. value={name}
  133. autoComplete='new-password'
  134. required={!isEdit}
  135. />
  136. <Divider/>
  137. <DatePicker
  138. label='过期时间'
  139. name='expired_time'
  140. placeholder={'请选择过期时间'}
  141. onChange={(value) => handleInputChange('expired_time', value)}
  142. value={expired_time}
  143. autoComplete='new-password'
  144. type='dateTime'
  145. />
  146. <div style={{ marginTop: 20 }}>
  147. <Space>
  148. <Button type={'tertiary'} onClick={() => {
  149. setExpiredTime(0, 0, 0, 0);
  150. }}>永不过期</Button>
  151. <Button type={'tertiary'} onClick={() => {
  152. setExpiredTime(0, 0, 1, 0);
  153. }}>一小时</Button>
  154. <Button type={'tertiary'} onClick={() => {
  155. setExpiredTime(1, 0, 0, 0);
  156. }}>一个月</Button>
  157. <Button type={'tertiary'} onClick={() => {
  158. setExpiredTime(0, 1, 0, 0);
  159. }}>一天</Button>
  160. </Space>
  161. </div>
  162. <Divider/>
  163. <Banner type={'warning'} description={'注意,令牌的额度仅用于限制令牌本身的最大额度使用量,实际的使用受到账户的剩余额度限制。'}></Banner>
  164. <div style={{ marginTop: 20 }}>
  165. <Typography.Text>{`额度${renderQuotaWithPrompt(remain_quota)}`}</Typography.Text>
  166. </div>
  167. <AutoComplete
  168. style={{ marginTop: 8 }}
  169. name='remain_quota'
  170. placeholder={'请输入额度'}
  171. onChange={(value) => handleInputChange('remain_quota', value)}
  172. value={remain_quota}
  173. autoComplete='new-password'
  174. type='number'
  175. position={'top'}
  176. data={[
  177. {value: 500000, label: '1$'},
  178. {value: 5000000, label: '10$'},
  179. {value: 25000000, label: '50$'},
  180. {value: 50000000, label: '100$'},
  181. {value: 250000000, label: '500$'},
  182. {value: 500000000, label: '1000$'},
  183. ]}
  184. disabled={unlimited_quota}
  185. />
  186. <div>
  187. <Button style={{ marginTop: 8 }} type={'warning'} onClick={() => {
  188. setUnlimitedQuota();
  189. }}>{unlimited_quota ? '取消无限额度' : '设为无限额度'}</Button>
  190. </div>
  191. </Spin>
  192. </SideSheet>
  193. </>
  194. );
  195. };
  196. export default EditToken;