diff --git a/controller/misc.go b/controller/misc.go
index ccbdecb5..33a41302 100644
--- a/controller/misc.go
+++ b/controller/misc.go
@@ -38,52 +38,71 @@ func TestStatus(c *gin.Context) {
func GetStatus(c *gin.Context) {
+ cs := console_setting.GetConsoleSetting()
+
+ data := gin.H{
+ "version": common.Version,
+ "start_time": common.StartTime,
+ "email_verification": common.EmailVerificationEnabled,
+ "github_oauth": common.GitHubOAuthEnabled,
+ "github_client_id": common.GitHubClientId,
+ "linuxdo_oauth": common.LinuxDOOAuthEnabled,
+ "linuxdo_client_id": common.LinuxDOClientId,
+ "telegram_oauth": common.TelegramOAuthEnabled,
+ "telegram_bot_name": common.TelegramBotName,
+ "system_name": common.SystemName,
+ "logo": common.Logo,
+ "footer_html": common.Footer,
+ "wechat_qrcode": common.WeChatAccountQRCodeImageURL,
+ "wechat_login": common.WeChatAuthEnabled,
+ "server_address": setting.ServerAddress,
+ "price": setting.Price,
+ "min_topup": setting.MinTopUp,
+ "turnstile_check": common.TurnstileCheckEnabled,
+ "turnstile_site_key": common.TurnstileSiteKey,
+ "top_up_link": common.TopUpLink,
+ "docs_link": operation_setting.GetGeneralSetting().DocsLink,
+ "quota_per_unit": common.QuotaPerUnit,
+ "display_in_currency": common.DisplayInCurrencyEnabled,
+ "enable_batch_update": common.BatchUpdateEnabled,
+ "enable_drawing": common.DrawingEnabled,
+ "enable_task": common.TaskEnabled,
+ "enable_data_export": common.DataExportEnabled,
+ "data_export_default_time": common.DataExportDefaultTime,
+ "default_collapse_sidebar": common.DefaultCollapseSidebar,
+ "enable_online_topup": setting.PayAddress != "" && setting.EpayId != "" && setting.EpayKey != "",
+ "mj_notify_enabled": setting.MjNotifyEnabled,
+ "chats": setting.Chats,
+ "demo_site_enabled": operation_setting.DemoSiteEnabled,
+ "self_use_mode_enabled": operation_setting.SelfUseModeEnabled,
+
+ // 面板启用开关
+ "api_info_enabled": cs.ApiInfoEnabled,
+ "uptime_kuma_enabled": cs.UptimeKumaEnabled,
+ "announcements_enabled": cs.AnnouncementsEnabled,
+ "faq_enabled": cs.FAQEnabled,
+
+ "oidc_enabled": system_setting.GetOIDCSettings().Enabled,
+ "oidc_client_id": system_setting.GetOIDCSettings().ClientId,
+ "oidc_authorization_endpoint": system_setting.GetOIDCSettings().AuthorizationEndpoint,
+ "setup": constant.Setup,
+ }
+
+ // 根据启用状态注入可选内容
+ if cs.ApiInfoEnabled {
+ data["api_info"] = console_setting.GetApiInfo()
+ }
+ if cs.AnnouncementsEnabled {
+ data["announcements"] = console_setting.GetAnnouncements()
+ }
+ if cs.FAQEnabled {
+ data["faq"] = console_setting.GetFAQ()
+ }
+
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
- "data": gin.H{
- "version": common.Version,
- "start_time": common.StartTime,
- "email_verification": common.EmailVerificationEnabled,
- "github_oauth": common.GitHubOAuthEnabled,
- "github_client_id": common.GitHubClientId,
- "linuxdo_oauth": common.LinuxDOOAuthEnabled,
- "linuxdo_client_id": common.LinuxDOClientId,
- "telegram_oauth": common.TelegramOAuthEnabled,
- "telegram_bot_name": common.TelegramBotName,
- "system_name": common.SystemName,
- "logo": common.Logo,
- "footer_html": common.Footer,
- "wechat_qrcode": common.WeChatAccountQRCodeImageURL,
- "wechat_login": common.WeChatAuthEnabled,
- "server_address": setting.ServerAddress,
- "price": setting.Price,
- "min_topup": setting.MinTopUp,
- "turnstile_check": common.TurnstileCheckEnabled,
- "turnstile_site_key": common.TurnstileSiteKey,
- "top_up_link": common.TopUpLink,
- "docs_link": operation_setting.GetGeneralSetting().DocsLink,
- "quota_per_unit": common.QuotaPerUnit,
- "display_in_currency": common.DisplayInCurrencyEnabled,
- "enable_batch_update": common.BatchUpdateEnabled,
- "enable_drawing": common.DrawingEnabled,
- "enable_task": common.TaskEnabled,
- "enable_data_export": common.DataExportEnabled,
- "data_export_default_time": common.DataExportDefaultTime,
- "default_collapse_sidebar": common.DefaultCollapseSidebar,
- "enable_online_topup": setting.PayAddress != "" && setting.EpayId != "" && setting.EpayKey != "",
- "mj_notify_enabled": setting.MjNotifyEnabled,
- "chats": setting.Chats,
- "demo_site_enabled": operation_setting.DemoSiteEnabled,
- "self_use_mode_enabled": operation_setting.SelfUseModeEnabled,
- "oidc_enabled": system_setting.GetOIDCSettings().Enabled,
- "oidc_client_id": system_setting.GetOIDCSettings().ClientId,
- "oidc_authorization_endpoint": system_setting.GetOIDCSettings().AuthorizationEndpoint,
- "setup": constant.Setup,
- "api_info": console_setting.GetApiInfo(),
- "announcements": console_setting.GetAnnouncements(),
- "faq": console_setting.GetFAQ(),
- },
+ "data": data,
})
return
}
diff --git a/setting/console_setting/config.go b/setting/console_setting/config.go
index 1379380e..063130fc 100644
--- a/setting/console_setting/config.go
+++ b/setting/console_setting/config.go
@@ -8,6 +8,10 @@ type ConsoleSetting struct {
UptimeKumaSlug string `json:"uptime_kuma_slug"` // Uptime Kuma Status Page Slug
Announcements string `json:"announcements"` // 系统公告 (JSON 数组字符串)
FAQ string `json:"faq"` // 常见问题 (JSON 数组字符串)
+ ApiInfoEnabled bool `json:"api_info_enabled"` // 是否启用 API 信息面板
+ UptimeKumaEnabled bool `json:"uptime_kuma_enabled"` // 是否启用 Uptime Kuma 面板
+ AnnouncementsEnabled bool `json:"announcements_enabled"` // 是否启用系统公告面板
+ FAQEnabled bool `json:"faq_enabled"` // 是否启用常见问答面板
}
// 默认配置
@@ -17,6 +21,10 @@ var defaultConsoleSetting = ConsoleSetting{
UptimeKumaSlug: "",
Announcements: "",
FAQ: "",
+ ApiInfoEnabled: true,
+ UptimeKumaEnabled: true,
+ AnnouncementsEnabled: true,
+ FAQEnabled: true,
}
// 全局实例
diff --git a/web/src/components/settings/DashboardSetting.js b/web/src/components/settings/DashboardSetting.js
index 7021c7ca..0546ca21 100644
--- a/web/src/components/settings/DashboardSetting.js
+++ b/web/src/components/settings/DashboardSetting.js
@@ -13,6 +13,10 @@ const DashboardSetting = () => {
'console_setting.faq': '',
'console_setting.uptime_kuma_url': '',
'console_setting.uptime_kuma_slug': '',
+ 'console_setting.api_info_enabled': '',
+ 'console_setting.announcements_enabled': '',
+ 'console_setting.faq_enabled': '',
+ 'console_setting.uptime_kuma_enabled': '',
// 用于迁移检测的旧键,下个版本会删除
ApiInfo: '',
diff --git a/web/src/pages/Detail/index.js b/web/src/pages/Detail/index.js
index f1d23871..747c1cf6 100644
--- a/web/src/pages/Detail/index.js
+++ b/web/src/pages/Detail/index.js
@@ -90,6 +90,15 @@ const Detail = (props) => {
let now = new Date();
const isAdminUser = isAdmin();
+ // ========== Panel enable flags ==========
+ const apiInfoEnabled = statusState?.status?.api_info_enabled ?? true;
+ const announcementsEnabled = statusState?.status?.announcements_enabled ?? true;
+ const faqEnabled = statusState?.status?.faq_enabled ?? true;
+ const uptimeEnabled = statusState?.status?.uptime_kuma_enabled ?? true;
+
+ const hasApiInfoPanel = apiInfoEnabled;
+ const hasInfoPanels = announcementsEnabled || faqEnabled || uptimeEnabled;
+
// ========== Helper Functions ==========
const getDefaultTime = useCallback(() => {
return localStorage.getItem('data_export_default_time') || 'hour';
@@ -1015,10 +1024,10 @@ const Detail = (props) => {
-
+
@@ -1061,7 +1070,7 @@ const Detail = (props) => {
- {!statusState?.status?.self_use_mode_enabled && (
+ {hasApiInfoPanel && (
{
{/* 系统公告和常见问答卡片 */}
- {!statusState?.status?.self_use_mode_enabled && (
+ {hasInfoPanels && (
{/* 公告卡片 */}
-
-
-
- {t('系统公告')}
-
- {t('显示最新20条')}
-
-
- {/* 图例 */}
-
- {announcementLegendData.map((legend, index) => (
-
- ))}
-
-
- }
- >
-
-
handleCardScroll(announcementScrollRef, setShowAnnouncementScrollHint)}
- >
- {announcementData.length > 0 ? (
-
- ) : (
-
-
}
- darkModeImage={
}
- title={t('暂无系统公告')}
- description={t('请联系管理员在系统设置中配置公告信息')}
- style={{ padding: '12px' }}
- />
+ {announcementsEnabled && (
+
+
+
+ {t('系统公告')}
+
+ {t('显示最新20条')}
+
- )}
-
-
-
-
-
- {/* 常见问答卡片 */}
-
-
- {t('常见问答')}
-
- }
- >
-
-
handleCardScroll(faqScrollRef, setShowFaqScrollHint)}
- >
- {faqData.length > 0 ? (
-
}
- collapseIcon={
}
- >
- {faqData.map((item, index) => (
-
- {item.answer}
-
- ))}
-
- ) : (
-
- }
- darkModeImage={}
- title={t('暂无常见问答')}
- description={t('请联系管理员在系统设置中配置常见问答')}
- style={{ padding: '12px' }}
- />
-
- )}
-
-
-
-
-
- {/* 服务可用性卡片 */}
-
-
-
- {t('服务可用性')}
-
- }
- onClick={loadUptimeData}
- loading={uptimeLoading}
- size="small"
- theme="borderless"
- className="text-gray-500 hover:text-blue-500 hover:bg-blue-50 !rounded-full"
- />
-
- }
- footer={uptimeData.length > 0 ? (
-
-
- {uptimeLegendData.map((legend, index) => (
-
- ))}
-
-
- ) : null}
- footerStyle={uptimeData.length > 0 ? { padding: '0px' } : undefined}
- >
-
-
- handleCardScroll(uptimeScrollRef, setShowUptimeScrollHint)}
- >
- {uptimeData.length > 0 ? (
- uptimeData.map((monitor, idx) => (
-
-
-
-
{((monitor.uptime || 0) * 100).toFixed(2)}%
-
-
-
{getUptimeStatusText(monitor.status)}
-
-
+ {/* 图例 */}
+
+ {announcementLegendData.map((legend, index) => (
+
- ))
+ ))}
+
+
+ }
+ >
+
+
handleCardScroll(announcementScrollRef, setShowAnnouncementScrollHint)}
+ >
+ {announcementData.length > 0 ? (
+
) : (
}
darkModeImage={}
- title={t('暂无监控数据')}
- description={t('请联系管理员在系统设置中配置Uptime')}
+ title={t('暂无系统公告')}
+ description={t('请联系管理员在系统设置中配置公告信息')}
style={{ padding: '12px' }}
/>
)}
-
-
-
-
+
+
+
+ )}
+
+ {/* 常见问答卡片 */}
+ {faqEnabled && (
+
+
+ {t('常见问答')}
+
+ }
+ >
+
+
handleCardScroll(faqScrollRef, setShowFaqScrollHint)}
+ >
+ {faqData.length > 0 ? (
+
}
+ collapseIcon={
}
+ >
+ {faqData.map((item, index) => (
+
+ {item.answer}
+
+ ))}
+
+ ) : (
+
+ }
+ darkModeImage={}
+ title={t('暂无常见问答')}
+ description={t('请联系管理员在系统设置中配置常见问答')}
+ style={{ padding: '12px' }}
+ />
+
+ )}
+
+
+
+
+ )}
+
+ {/* 服务可用性卡片 */}
+ {uptimeEnabled && (
+
+
+
+ {t('服务可用性')}
+
+ }
+ onClick={loadUptimeData}
+ loading={uptimeLoading}
+ size="small"
+ theme="borderless"
+ className="text-gray-500 hover:text-blue-500 hover:bg-blue-50 !rounded-full"
+ />
+
+ }
+ footer={uptimeData.length > 0 ? (
+
+
+ {uptimeLegendData.map((legend, index) => (
+
+ ))}
+
+
+ ) : null}
+ footerStyle={uptimeData.length > 0 ? { padding: '0px' } : undefined}
+ >
+
+
+ handleCardScroll(uptimeScrollRef, setShowUptimeScrollHint)}
+ >
+ {uptimeData.length > 0 ? (
+ uptimeData.map((monitor, idx) => (
+
+
+
+
{((monitor.uptime || 0) * 100).toFixed(2)}%
+
+
+
{getUptimeStatusText(monitor.status)}
+
+
+
+ ))
+ ) : (
+
+ }
+ darkModeImage={}
+ title={t('暂无监控数据')}
+ description={t('请联系管理员在系统设置中配置Uptime')}
+ style={{ padding: '12px' }}
+ />
+
+ )}
+
+
+
+
+
+ )}
)}
diff --git a/web/src/pages/Setting/Dashboard/SettingsAPIInfo.js b/web/src/pages/Setting/Dashboard/SettingsAPIInfo.js
index 7cb7275b..6a80b358 100644
--- a/web/src/pages/Setting/Dashboard/SettingsAPIInfo.js
+++ b/web/src/pages/Setting/Dashboard/SettingsAPIInfo.js
@@ -9,7 +9,8 @@ import {
Divider,
Avatar,
Modal,
- Tag
+ Tag,
+ Switch
} from '@douyinfe/semi-ui';
import {
IllustrationNoResult,
@@ -48,6 +49,9 @@ const SettingsAPIInfo = ({ options, refresh }) => {
const [pageSize, setPageSize] = useState(10);
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
+ // 面板启用状态 state
+ const [panelEnabled, setPanelEnabled] = useState(true);
+
const colorOptions = [
{ value: 'blue', label: 'blue' },
{ value: 'green', label: 'green' },
@@ -191,6 +195,30 @@ const SettingsAPIInfo = ({ options, refresh }) => {
}
}, [options['console_setting.api_info'], options.ApiInfo]);
+ useEffect(() => {
+ const enabledStr = options['console_setting.api_info_enabled'];
+ setPanelEnabled(enabledStr === undefined ? true : enabledStr === 'true' || enabledStr === true);
+ }, [options['console_setting.api_info_enabled']]);
+
+ const handleToggleEnabled = async (checked) => {
+ const newValue = checked ? 'true' : 'false';
+ try {
+ const res = await API.put('/api/option/', {
+ key: 'console_setting.api_info_enabled',
+ value: newValue,
+ });
+ if (res.data.success) {
+ setPanelEnabled(checked);
+ showSuccess(t('设置已保存'));
+ refresh?.();
+ } else {
+ showError(res.data.message);
+ }
+ } catch (err) {
+ showError(err.message);
+ }
+ };
+
const columns = [
{
title: 'ID',
@@ -325,6 +353,15 @@ const SettingsAPIInfo = ({ options, refresh }) => {
{t('保存设置')}
+
+ {/* 启用开关 */}
+
+
+ {panelEnabled ? t('已启用') : t('已禁用')}
+
);
diff --git a/web/src/pages/Setting/Dashboard/SettingsAnnouncements.js b/web/src/pages/Setting/Dashboard/SettingsAnnouncements.js
index caa632e1..f1b99f43 100644
--- a/web/src/pages/Setting/Dashboard/SettingsAnnouncements.js
+++ b/web/src/pages/Setting/Dashboard/SettingsAnnouncements.js
@@ -8,7 +8,8 @@ import {
Empty,
Divider,
Modal,
- Tag
+ Tag,
+ Switch
} from '@douyinfe/semi-ui';
import {
IllustrationNoResult,
@@ -47,6 +48,9 @@ const SettingsAnnouncements = ({ options, refresh }) => {
const [pageSize, setPageSize] = useState(10);
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
+ // 面板启用状态
+ const [panelEnabled, setPanelEnabled] = useState(true);
+
const typeOptions = [
{ value: 'default', label: t('默认') },
{ value: 'ongoing', label: t('进行中') },
@@ -294,6 +298,30 @@ const SettingsAnnouncements = ({ options, refresh }) => {
}
}, [options['console_setting.announcements'], options.Announcements]);
+ useEffect(() => {
+ const enabledStr = options['console_setting.announcements_enabled'];
+ setPanelEnabled(enabledStr === undefined ? true : enabledStr === 'true' || enabledStr === true);
+ }, [options['console_setting.announcements_enabled']]);
+
+ const handleToggleEnabled = async (checked) => {
+ const newValue = checked ? 'true' : 'false';
+ try {
+ const res = await API.put('/api/option/', {
+ key: 'console_setting.announcements_enabled',
+ value: newValue,
+ });
+ if (res.data.success) {
+ setPanelEnabled(checked);
+ showSuccess(t('设置已保存'));
+ refresh?.();
+ } else {
+ showError(res.data.message);
+ }
+ } catch (err) {
+ showError(err.message);
+ }
+ };
+
const handleBatchDelete = () => {
if (selectedRowKeys.length === 0) {
showError('请先选择要删除的系统公告');
@@ -350,6 +378,12 @@ const SettingsAnnouncements = ({ options, refresh }) => {
{t('保存设置')}
+
+ {/* 启用开关 */}
+
+
+ {panelEnabled ? t('已启用') : t('已禁用')}
+
);
diff --git a/web/src/pages/Setting/Dashboard/SettingsFAQ.js b/web/src/pages/Setting/Dashboard/SettingsFAQ.js
index d1211899..0e029e13 100644
--- a/web/src/pages/Setting/Dashboard/SettingsFAQ.js
+++ b/web/src/pages/Setting/Dashboard/SettingsFAQ.js
@@ -7,7 +7,8 @@ import {
Typography,
Empty,
Divider,
- Modal
+ Modal,
+ Switch
} from '@douyinfe/semi-ui';
import {
IllustrationNoResult,
@@ -44,6 +45,9 @@ const SettingsFAQ = ({ options, refresh }) => {
const [pageSize, setPageSize] = useState(10);
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
+ // 面板启用状态
+ const [panelEnabled, setPanelEnabled] = useState(true);
+
const columns = [
{
title: t('问题标题'),
@@ -231,6 +235,30 @@ const SettingsFAQ = ({ options, refresh }) => {
}
}, [options['console_setting.faq']]);
+ useEffect(() => {
+ const enabledStr = options['console_setting.faq_enabled'];
+ setPanelEnabled(enabledStr === undefined ? true : enabledStr === 'true' || enabledStr === true);
+ }, [options['console_setting.faq_enabled']]);
+
+ const handleToggleEnabled = async (checked) => {
+ const newValue = checked ? 'true' : 'false';
+ try {
+ const res = await API.put('/api/option/', {
+ key: 'console_setting.faq_enabled',
+ value: newValue,
+ });
+ if (res.data.success) {
+ setPanelEnabled(checked);
+ showSuccess(t('设置已保存'));
+ refresh?.();
+ } else {
+ showError(res.data.message);
+ }
+ } catch (err) {
+ showError(err.message);
+ }
+ };
+
const handleBatchDelete = () => {
if (selectedRowKeys.length === 0) {
showError('请先选择要删除的常见问答');
@@ -287,6 +315,12 @@ const SettingsFAQ = ({ options, refresh }) => {
{t('保存设置')}
+
+ {/* 启用开关 */}
+
+
+ {panelEnabled ? t('已启用') : t('已禁用')}
+
);
diff --git a/web/src/pages/Setting/Dashboard/SettingsUptimeKuma.js b/web/src/pages/Setting/Dashboard/SettingsUptimeKuma.js
index 58f8fedf..d489b683 100644
--- a/web/src/pages/Setting/Dashboard/SettingsUptimeKuma.js
+++ b/web/src/pages/Setting/Dashboard/SettingsUptimeKuma.js
@@ -5,6 +5,7 @@ import {
Typography,
Row,
Col,
+ Switch,
} from '@douyinfe/semi-ui';
import {
Save,
@@ -19,6 +20,7 @@ const SettingsUptimeKuma = ({ options, refresh }) => {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
+ const [panelEnabled, setPanelEnabled] = useState(true);
const formApiRef = useRef(null);
const initValues = useMemo(() => ({
@@ -32,6 +34,11 @@ const SettingsUptimeKuma = ({ options, refresh }) => {
}
}, [initValues]);
+ useEffect(() => {
+ const enabledStr = options?.['console_setting.uptime_kuma_enabled'];
+ setPanelEnabled(enabledStr === undefined ? true : enabledStr === 'true' || enabledStr === true);
+ }, [options?.['console_setting.uptime_kuma_enabled']]);
+
const handleSave = async () => {
const api = formApiRef.current;
if (!api) {
@@ -75,6 +82,25 @@ const SettingsUptimeKuma = ({ options, refresh }) => {
}
};
+ const handleToggleEnabled = async (checked) => {
+ const newValue = checked ? 'true' : 'false';
+ try {
+ const res = await API.put('/api/option/', {
+ key: 'console_setting.uptime_kuma_enabled',
+ value: newValue,
+ });
+ if (res.data.success) {
+ setPanelEnabled(checked);
+ showSuccess(t('设置已保存'));
+ refresh?.();
+ } else {
+ showError(res.data.message);
+ }
+ } catch (err) {
+ showError(err.message);
+ }
+ };
+
const isValidUrl = useCallback((string) => {
try {
new URL(string);
@@ -103,7 +129,7 @@ const SettingsUptimeKuma = ({ options, refresh }) => {
-
+
}
theme='solid'
@@ -114,6 +140,9 @@ const SettingsUptimeKuma = ({ options, refresh }) => {
>
{t('保存设置')}
+
+
+ {panelEnabled ? t('已启用') : t('已禁用')}