OtherSetting.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. import React, { useEffect, useState } from 'react';
  2. import { Button, Divider, Form, Grid, Header, Message, Modal } from 'semantic-ui-react';
  3. import { API, showError, showSuccess } from '../helpers';
  4. import { marked } from 'marked';
  5. const OtherSetting = () => {
  6. let [inputs, setInputs] = useState({
  7. Footer: '',
  8. Notice: '',
  9. About: '',
  10. SystemName: '',
  11. Logo: '',
  12. HomePageContent: ''
  13. });
  14. let [loading, setLoading] = useState(false);
  15. const [showUpdateModal, setShowUpdateModal] = useState(false);
  16. const [updateData, setUpdateData] = useState({
  17. tag_name: '',
  18. content: ''
  19. });
  20. const getOptions = async () => {
  21. const res = await API.get('/api/option/');
  22. const { success, message, data } = res.data;
  23. if (success) {
  24. let newInputs = {};
  25. data.forEach((item) => {
  26. if (item.key in inputs) {
  27. newInputs[item.key] = item.value;
  28. }
  29. });
  30. setInputs(newInputs);
  31. } else {
  32. showError(message);
  33. }
  34. };
  35. useEffect(() => {
  36. getOptions().then();
  37. }, []);
  38. const updateOption = async (key, value) => {
  39. setLoading(true);
  40. const res = await API.put('/api/option/', {
  41. key,
  42. value
  43. });
  44. const { success, message } = res.data;
  45. if (success) {
  46. setInputs((inputs) => ({ ...inputs, [key]: value }));
  47. } else {
  48. showError(message);
  49. }
  50. setLoading(false);
  51. };
  52. const handleInputChange = async (e, { name, value }) => {
  53. setInputs((inputs) => ({ ...inputs, [name]: value }));
  54. };
  55. const submitNotice = async () => {
  56. await updateOption('Notice', inputs.Notice);
  57. };
  58. const submitFooter = async () => {
  59. await updateOption('Footer', inputs.Footer);
  60. };
  61. const submitSystemName = async () => {
  62. await updateOption('SystemName', inputs.SystemName);
  63. };
  64. const submitLogo = async () => {
  65. await updateOption('Logo', inputs.Logo);
  66. };
  67. const submitAbout = async () => {
  68. await updateOption('About', inputs.About);
  69. };
  70. const submitOption = async (key) => {
  71. await updateOption(key, inputs[key]);
  72. };
  73. const openGitHubRelease = () => {
  74. window.location =
  75. 'https://github.com/songquanpeng/one-api/releases/latest';
  76. };
  77. const checkUpdate = async () => {
  78. const res = await API.get(
  79. 'https://api.github.com/repos/songquanpeng/one-api/releases/latest'
  80. );
  81. const { tag_name, body } = res.data;
  82. if (tag_name === process.env.REACT_APP_VERSION) {
  83. showSuccess(`已是最新版本:${tag_name}`);
  84. } else {
  85. setUpdateData({
  86. tag_name: tag_name,
  87. content: marked.parse(body)
  88. });
  89. setShowUpdateModal(true);
  90. }
  91. };
  92. return (
  93. <Grid columns={1}>
  94. <Grid.Column>
  95. <Form loading={loading}>
  96. <Header as='h3'>通用设置</Header>
  97. <Form.Button onClick={checkUpdate}>检查更新</Form.Button>
  98. <Form.Group widths='equal'>
  99. <Form.TextArea
  100. label='公告'
  101. placeholder='在此输入新的公告内容'
  102. value={inputs.Notice}
  103. name='Notice'
  104. onChange={handleInputChange}
  105. style={{ minHeight: 150, fontFamily: 'JetBrains Mono, Consolas' }}
  106. />
  107. </Form.Group>
  108. <Form.Button onClick={submitNotice}>保存公告</Form.Button>
  109. <Divider />
  110. <Header as='h3'>个性化设置</Header>
  111. <Form.Group widths='equal'>
  112. <Form.Input
  113. label='系统名称'
  114. placeholder='在此输入系统名称'
  115. value={inputs.SystemName}
  116. name='SystemName'
  117. onChange={handleInputChange}
  118. />
  119. </Form.Group>
  120. <Form.Button onClick={submitSystemName}>设置系统名称</Form.Button>
  121. <Form.Group widths='equal'>
  122. <Form.Input
  123. label='Logo 图片地址'
  124. placeholder='在此输入 Logo 图片地址'
  125. value={inputs.Logo}
  126. name='Logo'
  127. type='url'
  128. onChange={handleInputChange}
  129. />
  130. </Form.Group>
  131. <Form.Button onClick={submitLogo}>设置 Logo</Form.Button>
  132. <Form.Group widths='equal'>
  133. <Form.TextArea
  134. label='首页内容'
  135. placeholder='在此输入首页内容,支持 Markdown & HTML 代码,设置后首页的状态信息将不再显示。如果输入的是一个链接,则会使用该链接作为 iframe 的 src 属性,这允许你设置任意网页作为首页。'
  136. value={inputs.HomePageContent}
  137. name='HomePageContent'
  138. onChange={handleInputChange}
  139. style={{ minHeight: 150, fontFamily: 'JetBrains Mono, Consolas' }}
  140. />
  141. </Form.Group>
  142. <Form.Button onClick={() => submitOption('HomePageContent')}>保存首页内容</Form.Button>
  143. <Form.Group widths='equal'>
  144. <Form.TextArea
  145. label='关于'
  146. placeholder='在此输入新的关于内容,支持 Markdown & HTML 代码。如果输入的是一个链接,则会使用该链接作为 iframe 的 src 属性,这允许你设置任意网页作为关于页面。'
  147. value={inputs.About}
  148. name='About'
  149. onChange={handleInputChange}
  150. style={{ minHeight: 150, fontFamily: 'JetBrains Mono, Consolas' }}
  151. />
  152. </Form.Group>
  153. <Form.Button onClick={submitAbout}>保存关于</Form.Button>
  154. <Message>移除 One API 的版权标识必须首先获得授权,后续版本将通过授权码强制执行。</Message>
  155. <Form.Group widths='equal'>
  156. <Form.Input
  157. label='页脚'
  158. placeholder='在此输入新的页脚,留空则使用默认页脚,支持 HTML 代码'
  159. value={inputs.Footer}
  160. name='Footer'
  161. onChange={handleInputChange}
  162. />
  163. </Form.Group>
  164. <Form.Button onClick={submitFooter}>设置页脚</Form.Button>
  165. </Form>
  166. </Grid.Column>
  167. <Modal
  168. onClose={() => setShowUpdateModal(false)}
  169. onOpen={() => setShowUpdateModal(true)}
  170. open={showUpdateModal}
  171. >
  172. <Modal.Header>新版本:{updateData.tag_name}</Modal.Header>
  173. <Modal.Content>
  174. <Modal.Description>
  175. <div dangerouslySetInnerHTML={{ __html: updateData.content }}></div>
  176. </Modal.Description>
  177. </Modal.Content>
  178. <Modal.Actions>
  179. <Button onClick={() => setShowUpdateModal(false)}>关闭</Button>
  180. <Button
  181. content='详情'
  182. onClick={() => {
  183. setShowUpdateModal(false);
  184. openGitHubRelease();
  185. }}
  186. />
  187. </Modal.Actions>
  188. </Modal>
  189. </Grid>
  190. );
  191. };
  192. export default OtherSetting;