1、后台系统设置settings页面增加一个开启关闭网站的按钮

2、如果网站关闭,前台页面所有请求暂时跳转单独的页如果网站关闭,前台页面所有请求暂时跳转单独的页面,页面内容 系统正在升级相关信息
3、要提供一个开发人员可以查看真实网站内容的入口
This commit is contained in:
2026-07-11 10:58:48 +08:00
parent 111c74c7c6
commit d2a30c58ca
11 changed files with 461 additions and 5 deletions
+4
View File
@@ -224,6 +224,10 @@ export async function updateSystemConfig(id: string, value: string): Promise<voi
await api.put(`/admin/system-configs/${id}`, { value });
}
export async function regenerateDevToken(): Promise<{ token: string }> {
return api.post('/admin/system-configs/regenerate-dev-token');
}
export async function getGlobalResourceCapacity(): Promise<ResourceCapacityConfigOut> {
return api.get('/admin/resource-capacity/global');
}
+85 -2
View File
@@ -1,9 +1,10 @@
import React, { useEffect, useState } from 'react';
import {
Button, Card, Form, Input, InputNumber, message, Select, Space, Switch, Typography, Upload,
Button, Card, Form, Input, InputNumber, message, Popconfirm, Select, Space, Switch, Typography, Upload,
} from 'antd';
import {
SettingOutlined, SaveOutlined, UploadOutlined, FilePdfOutlined, EyeOutlined, DatabaseOutlined,
PoweroffOutlined, ReloadOutlined, CopyOutlined,
} from '@ant-design/icons';
import {
getGlobalResourceCapacity,
@@ -12,6 +13,7 @@ import {
updateSystemConfig,
uploadLogo,
uploadPdf,
regenerateDevToken,
} from '../api';
import type { ResourceCapacityUnit, SystemConfig } from '../types';
@@ -42,6 +44,8 @@ const AdminSettings: React.FC = () => {
setConfigs(data);
const formValues: Record<string, any> = {};
data.forEach(c => { formValues[c.key] = c.value; });
// 网站开关布尔值转换
formValues.site_enabled = siteEnabledConfig?.value !== 'false';
formValues.resource_capacity_enabled = capacity.enabled;
formValues.resource_capacity_limit_value = capacity.limitValue || '1.000';
formValues.resource_capacity_limit_unit = capacity.limitUnit || 'GB';
@@ -63,6 +67,13 @@ const AdminSettings: React.FC = () => {
await updateSystemConfig(config.id, String(newVal ?? ''));
}
}
// 保存网站开关(布尔值转为字符串)
if (siteEnabledConfig) {
const newEnabled = values.site_enabled ? 'true' : 'false';
if (newEnabled !== siteEnabledConfig.value) {
await updateSystemConfig(siteEnabledConfig.id, newEnabled);
}
}
await saveGlobalResourceCapacity({
enabled: !!values.resource_capacity_enabled,
limitValue: String(values.resource_capacity_limit_value ?? '1.000'),
@@ -77,6 +88,20 @@ const AdminSettings: React.FC = () => {
}
};
const handleRegenerateDevToken = async () => {
try {
const result = await regenerateDevToken();
message.success('开发者令牌已重新生成');
await load();
// 更新显示的令牌
if (result?.token) {
form.setFieldsValue({ site_dev_access_token: result.token });
}
} catch (e: any) {
message.error(e?.message || '重新生成失败');
}
};
const handleUpload = async (file: File, configKey: string) => {
setUploading(configKey);
try {
@@ -118,8 +143,11 @@ const AdminSettings: React.FC = () => {
return false;
};
const siteEnabledConfig = configs.find(c => c.key === 'site_enabled');
const devTokenConfig = configs.find(c => c.key === 'site_dev_access_token');
const groupedConfigs: Record<string, SystemConfig[]> = {
'站点信息': configs.filter(c => c.key.startsWith('site_')),
'站点信息': configs.filter(c => c.key.startsWith('site_') && c.key !== 'site_enabled' && c.key !== 'site_dev_access_token'),
'协议配置': configs.filter(c => c.key === 'user_agreement_privacy_url'),
'SEO 设置': configs.filter(c => c.key.startsWith('seo_')),
'用户积分配置': configs.filter(c => c.key.startsWith('user_') && c.key.includes('credits')),
@@ -297,6 +325,61 @@ const AdminSettings: React.FC = () => {
</div>
<Form form={form} layout="vertical">
{/* 网站访问控制 */}
<div style={{ marginBottom: 24 }}>
<Typography.Text strong style={{ fontSize: 14, display: 'block', marginBottom: 12, paddingBottom: 8, borderBottom: '1px solid #f0f0f5' }}>
访
</Typography.Text>
{siteEnabledConfig ? (
<Form.Item
name="site_enabled"
label="网站访问开关"
valuePropName="checked"
extra="关闭后前台所有用户将被重定向到维护页面(管理员仍可登录后台管理)"
>
<Switch checkedChildren="网站开启" unCheckedChildren="网站关闭" />
</Form.Item>
) : (
<Typography.Text type="secondary" style={{ fontSize: 13 }}>
site_enabled
</Typography.Text>
)}
{devTokenConfig && (
<Form.Item
label="开发者访问令牌"
extra="网站关闭时,在维护页面输入此令牌可正常访问前台内容。令牌仅管理员可见。"
>
<Space.Compact style={{ width: '100%' }}>
<Input.Password
name="site_dev_access_token"
readOnly
value={devTokenConfig.value}
style={{ fontFamily: 'monospace' }}
/>
<Button
icon={<CopyOutlined />}
onClick={() => {
navigator.clipboard.writeText(devTokenConfig.value);
message.success('已复制到剪贴板');
}}
>
</Button>
<Popconfirm
title="重新生成令牌?"
description="重新生成后旧令牌将立即失效,需要重新复制新令牌。"
onConfirm={handleRegenerateDevToken}
okText="确认"
cancelText="取消"
>
<Button icon={<ReloadOutlined />} danger></Button>
</Popconfirm>
</Space.Compact>
</Form.Item>
)}
</div>
{Object.entries(groupedConfigs).map(([group, items]) => (
<div key={group} style={{ marginBottom: 24 }}>
<Typography.Text strong style={{ fontSize: 14, display: 'block', marginBottom: 12, paddingBottom: 8, borderBottom: '1px solid #f0f0f5' }}>