DashboardSetting.jsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. Copyright (C) 2025 QuantumNous
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>.
  13. For commercial licensing, please contact support@quantumnous.com
  14. */
  15. import React, { useEffect, useState, useMemo } from 'react';
  16. import { Card, Spin, Button, Modal } from '@douyinfe/semi-ui';
  17. import { API, showError, showSuccess, toBoolean } from '../../helpers';
  18. import SettingsAPIInfo from '../../pages/Setting/Dashboard/SettingsAPIInfo';
  19. import SettingsAnnouncements from '../../pages/Setting/Dashboard/SettingsAnnouncements';
  20. import SettingsFAQ from '../../pages/Setting/Dashboard/SettingsFAQ';
  21. import SettingsUptimeKuma from '../../pages/Setting/Dashboard/SettingsUptimeKuma';
  22. import SettingsDataDashboard from '../../pages/Setting/Dashboard/SettingsDataDashboard';
  23. const DashboardSetting = () => {
  24. let [inputs, setInputs] = useState({
  25. 'console_setting.api_info': '',
  26. 'console_setting.announcements': '',
  27. 'console_setting.faq': '',
  28. 'console_setting.uptime_kuma_groups': '',
  29. 'console_setting.api_info_enabled': '',
  30. 'console_setting.announcements_enabled': '',
  31. 'console_setting.faq_enabled': '',
  32. 'console_setting.uptime_kuma_enabled': '',
  33. // 用于迁移检测的旧键,下个版本会删除
  34. ApiInfo: '',
  35. Announcements: '',
  36. FAQ: '',
  37. UptimeKumaUrl: '',
  38. UptimeKumaSlug: '',
  39. /* 数据看板 */
  40. DataExportEnabled: false,
  41. DataExportDefaultTime: 'hour',
  42. DataExportInterval: 5,
  43. });
  44. let [loading, setLoading] = useState(false);
  45. const [showMigrateModal, setShowMigrateModal] = useState(false); // 下个版本会删除
  46. const getOptions = async () => {
  47. const res = await API.get('/api/option/');
  48. const { success, message, data } = res.data;
  49. if (success) {
  50. let newInputs = {};
  51. data.forEach((item) => {
  52. if (item.key in inputs) {
  53. newInputs[item.key] = item.value;
  54. }
  55. if (item.key.endsWith('Enabled') && item.key === 'DataExportEnabled') {
  56. newInputs[item.key] = toBoolean(item.value);
  57. }
  58. });
  59. setInputs(newInputs);
  60. } else {
  61. showError(message);
  62. }
  63. };
  64. async function onRefresh() {
  65. try {
  66. setLoading(true);
  67. await getOptions();
  68. } catch (error) {
  69. showError('刷新失败');
  70. console.error(error);
  71. } finally {
  72. setLoading(false);
  73. }
  74. }
  75. useEffect(() => {
  76. onRefresh();
  77. }, []);
  78. // 用于迁移检测的旧键,下个版本会删除
  79. const hasLegacyData = useMemo(() => {
  80. const legacyKeys = [
  81. 'ApiInfo',
  82. 'Announcements',
  83. 'FAQ',
  84. 'UptimeKumaUrl',
  85. 'UptimeKumaSlug',
  86. ];
  87. return legacyKeys.some((k) => inputs[k]);
  88. }, [inputs]);
  89. useEffect(() => {
  90. if (hasLegacyData) {
  91. setShowMigrateModal(true);
  92. }
  93. }, [hasLegacyData]);
  94. const handleMigrate = async () => {
  95. try {
  96. setLoading(true);
  97. await API.post('/api/option/migrate_console_setting');
  98. showSuccess('旧配置迁移完成');
  99. await onRefresh();
  100. setShowMigrateModal(false);
  101. } catch (err) {
  102. console.error(err);
  103. showError('迁移失败: ' + (err.message || '未知错误'));
  104. } finally {
  105. setLoading(false);
  106. }
  107. };
  108. return (
  109. <>
  110. <Spin spinning={loading} size='large'>
  111. {/* 用于迁移检测的旧键模态框,下个版本会删除 */}
  112. <Modal
  113. title='配置迁移确认'
  114. visible={showMigrateModal}
  115. onOk={handleMigrate}
  116. onCancel={() => setShowMigrateModal(false)}
  117. confirmLoading={loading}
  118. okText='确认迁移'
  119. cancelText='取消'
  120. >
  121. <p>检测到旧版本的配置数据,是否要迁移到新的配置格式?</p>
  122. <p style={{ color: '#f57c00', marginTop: '10px' }}>
  123. <strong>注意:</strong>
  124. 迁移过程中会自动处理数据格式转换,迁移完成后旧配置将被清除,请在迁移前在数据库中备份好旧配置。
  125. </p>
  126. </Modal>
  127. {/* 数据看板设置 */}
  128. <Card style={{ marginTop: '10px' }}>
  129. <SettingsDataDashboard options={inputs} refresh={onRefresh} />
  130. </Card>
  131. {/* 系统公告管理 */}
  132. <Card style={{ marginTop: '10px' }}>
  133. <SettingsAnnouncements options={inputs} refresh={onRefresh} />
  134. </Card>
  135. {/* API信息管理 */}
  136. <Card style={{ marginTop: '10px' }}>
  137. <SettingsAPIInfo options={inputs} refresh={onRefresh} />
  138. </Card>
  139. {/* 常见问答管理 */}
  140. <Card style={{ marginTop: '10px' }}>
  141. <SettingsFAQ options={inputs} refresh={onRefresh} />
  142. </Card>
  143. {/* Uptime Kuma 监控设置 */}
  144. <Card style={{ marginTop: '10px' }}>
  145. <SettingsUptimeKuma options={inputs} refresh={onRefresh} />
  146. </Card>
  147. </Spin>
  148. </>
  149. );
  150. };
  151. export default DashboardSetting;