@@ -83,6 +83,7 @@ export function buildConfig(env: NodeJS.ProcessEnv) {
|
|||||||
telegramApiBaseUrl: 'https://api.telegram.org',
|
telegramApiBaseUrl: 'https://api.telegram.org',
|
||||||
telegramBotToken: env.TELEGRAM_BOT_TOKEN || '',
|
telegramBotToken: env.TELEGRAM_BOT_TOKEN || '',
|
||||||
telegramChatId: env.TELEGRAM_CHAT_ID || '',
|
telegramChatId: env.TELEGRAM_CHAT_ID || '',
|
||||||
|
telegramUseSystemProxy: parseBoolean(env.TELEGRAM_USE_SYSTEM_PROXY, false),
|
||||||
smtpEnabled: parseBoolean(env.SMTP_ENABLED, false),
|
smtpEnabled: parseBoolean(env.SMTP_ENABLED, false),
|
||||||
smtpHost: env.SMTP_HOST || '',
|
smtpHost: env.SMTP_HOST || '',
|
||||||
smtpPort: parseInt(env.SMTP_PORT || '587'),
|
smtpPort: parseInt(env.SMTP_PORT || '587'),
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ describe('settings and auth events', () => {
|
|||||||
(config as any).telegramApiBaseUrl = 'https://api.telegram.org';
|
(config as any).telegramApiBaseUrl = 'https://api.telegram.org';
|
||||||
(config as any).telegramBotToken = '';
|
(config as any).telegramBotToken = '';
|
||||||
(config as any).telegramChatId = '';
|
(config as any).telegramChatId = '';
|
||||||
|
(config as any).telegramUseSystemProxy = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
@@ -219,6 +220,32 @@ describe('settings and auth events', () => {
|
|||||||
expect(body.message).toContain('Telegram API Base URL');
|
expect(body.message).toContain('Telegram API Base URL');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('persists and returns telegram use system proxy from runtime settings', async () => {
|
||||||
|
const updateResponse = await app.inject({
|
||||||
|
method: 'PUT',
|
||||||
|
url: '/api/settings/runtime',
|
||||||
|
payload: {
|
||||||
|
telegramUseSystemProxy: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(updateResponse.statusCode).toBe(200);
|
||||||
|
const updated = updateResponse.json() as { telegramUseSystemProxy?: boolean };
|
||||||
|
expect(updated.telegramUseSystemProxy).toBe(true);
|
||||||
|
expect((config as any).telegramUseSystemProxy).toBe(true);
|
||||||
|
|
||||||
|
const saved = await db.select().from(schema.settings).where(eq(schema.settings.key, 'telegram_use_system_proxy')).get();
|
||||||
|
expect(saved?.value).toBe(JSON.stringify(true));
|
||||||
|
|
||||||
|
const getResponse = await app.inject({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/api/settings/runtime',
|
||||||
|
});
|
||||||
|
expect(getResponse.statusCode).toBe(200);
|
||||||
|
const runtime = getResponse.json() as { telegramUseSystemProxy?: boolean };
|
||||||
|
expect(runtime.telegramUseSystemProxy).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it('persists and returns routing fallback unit cost from runtime settings', async () => {
|
it('persists and returns routing fallback unit cost from runtime settings', async () => {
|
||||||
const updateResponse = await app.inject({
|
const updateResponse = await app.inject({
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { FastifyInstance } from 'fastify';
|
import { FastifyInstance } from 'fastify';
|
||||||
import cron from 'node-cron';
|
import cron from 'node-cron';
|
||||||
import { config } from '../../config.js';
|
import { config } from '../../config.js';
|
||||||
import { db, runtimeDbDialect, schema } from '../../db/index.js';
|
import { db, runtimeDbDialect, schema } from '../../db/index.js';
|
||||||
@@ -43,6 +43,7 @@ interface RuntimeSettingsBody {
|
|||||||
telegramApiBaseUrl?: string;
|
telegramApiBaseUrl?: string;
|
||||||
telegramBotToken?: string;
|
telegramBotToken?: string;
|
||||||
telegramChatId?: string;
|
telegramChatId?: string;
|
||||||
|
telegramUseSystemProxy?: boolean;
|
||||||
smtpEnabled?: boolean;
|
smtpEnabled?: boolean;
|
||||||
smtpHost?: string;
|
smtpHost?: string;
|
||||||
smtpPort?: number;
|
smtpPort?: number;
|
||||||
@@ -288,6 +289,10 @@ function applyImportedSettingToRuntime(key: string, value: unknown) {
|
|||||||
config.telegramChatId = value.trim();
|
config.telegramChatId = value.trim();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case 'telegram_use_system_proxy': {
|
||||||
|
config.telegramUseSystemProxy = !!value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
case 'smtp_enabled': {
|
case 'smtp_enabled': {
|
||||||
config.smtpEnabled = !!value;
|
config.smtpEnabled = !!value;
|
||||||
return;
|
return;
|
||||||
@@ -380,6 +385,7 @@ function getRuntimeSettingsResponse(currentAdminIp = '') {
|
|||||||
telegramApiBaseUrl: config.telegramApiBaseUrl,
|
telegramApiBaseUrl: config.telegramApiBaseUrl,
|
||||||
telegramBotTokenMasked: maskSecret(config.telegramBotToken),
|
telegramBotTokenMasked: maskSecret(config.telegramBotToken),
|
||||||
telegramChatId: config.telegramChatId,
|
telegramChatId: config.telegramChatId,
|
||||||
|
telegramUseSystemProxy: config.telegramUseSystemProxy,
|
||||||
smtpEnabled: config.smtpEnabled,
|
smtpEnabled: config.smtpEnabled,
|
||||||
smtpHost: config.smtpHost,
|
smtpHost: config.smtpHost,
|
||||||
smtpPort: config.smtpPort,
|
smtpPort: config.smtpPort,
|
||||||
@@ -512,7 +518,8 @@ export async function settingsRoutes(app: FastifyInstance) {
|
|||||||
const telegramTouched = body.telegramEnabled !== undefined
|
const telegramTouched = body.telegramEnabled !== undefined
|
||||||
|| body.telegramApiBaseUrl !== undefined
|
|| body.telegramApiBaseUrl !== undefined
|
||||||
|| body.telegramBotToken !== undefined
|
|| body.telegramBotToken !== undefined
|
||||||
|| body.telegramChatId !== undefined;
|
|| body.telegramChatId !== undefined
|
||||||
|
|| body.telegramUseSystemProxy !== undefined;
|
||||||
const nextTelegramEnabled = body.telegramEnabled !== undefined
|
const nextTelegramEnabled = body.telegramEnabled !== undefined
|
||||||
? !!body.telegramEnabled
|
? !!body.telegramEnabled
|
||||||
: config.telegramEnabled;
|
: config.telegramEnabled;
|
||||||
@@ -768,6 +775,14 @@ export async function settingsRoutes(app: FastifyInstance) {
|
|||||||
upsertSetting('telegram_chat_id', config.telegramChatId);
|
upsertSetting('telegram_chat_id', config.telegramChatId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (body.telegramUseSystemProxy !== undefined) {
|
||||||
|
if (!!body.telegramUseSystemProxy !== config.telegramUseSystemProxy) {
|
||||||
|
changedLabels.push('Telegram 使用系统代理');
|
||||||
|
}
|
||||||
|
config.telegramUseSystemProxy = !!body.telegramUseSystemProxy;
|
||||||
|
upsertSetting('telegram_use_system_proxy', config.telegramUseSystemProxy);
|
||||||
|
}
|
||||||
|
|
||||||
if (body.smtpEnabled !== undefined) {
|
if (body.smtpEnabled !== undefined) {
|
||||||
if (!!body.smtpEnabled !== config.smtpEnabled) {
|
if (!!body.smtpEnabled !== config.smtpEnabled) {
|
||||||
changedLabels.push('SMTP 开关');
|
changedLabels.push('SMTP 开关');
|
||||||
|
|||||||
@@ -17,12 +17,24 @@ vi.mock('undici', () => ({
|
|||||||
fetch: (...args: unknown[]) => fetchMock(...args),
|
fetch: (...args: unknown[]) => fetchMock(...args),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const withExplicitProxyRequestInitMock = vi.fn(
|
||||||
|
(_proxyUrl: unknown, options?: Record<string, unknown>) => {
|
||||||
|
if (_proxyUrl) return { ...(options || {}), dispatcher: 'mock-proxy-dispatcher' };
|
||||||
|
return options ?? {};
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
vi.mock('./siteProxy.js', () => ({
|
||||||
|
withExplicitProxyRequestInit: (...args: unknown[]) => withExplicitProxyRequestInitMock(...args),
|
||||||
|
}));
|
||||||
|
|
||||||
describe('notifyService', () => {
|
describe('notifyService', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
vi.resetModules();
|
vi.resetModules();
|
||||||
sendMailMock.mockReset();
|
sendMailMock.mockReset();
|
||||||
createTransportMock.mockClear();
|
createTransportMock.mockClear();
|
||||||
fetchMock.mockReset();
|
fetchMock.mockReset();
|
||||||
|
withExplicitProxyRequestInitMock.mockClear();
|
||||||
|
|
||||||
const { config } = await import('../config.js');
|
const { config } = await import('../config.js');
|
||||||
config.notifyCooldownSec = 300;
|
config.notifyCooldownSec = 300;
|
||||||
@@ -35,6 +47,8 @@ describe('notifyService', () => {
|
|||||||
(config as any).telegramEnabled = false;
|
(config as any).telegramEnabled = false;
|
||||||
(config as any).telegramBotToken = '';
|
(config as any).telegramBotToken = '';
|
||||||
(config as any).telegramChatId = '';
|
(config as any).telegramChatId = '';
|
||||||
|
(config as any).telegramUseSystemProxy = false;
|
||||||
|
config.systemProxyUrl = '';
|
||||||
config.smtpEnabled = true;
|
config.smtpEnabled = true;
|
||||||
config.smtpHost = 'smtp.example.com';
|
config.smtpHost = 'smtp.example.com';
|
||||||
config.smtpPort = 465;
|
config.smtpPort = 465;
|
||||||
@@ -222,4 +236,50 @@ describe('notifyService', () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('applies system proxy dispatcher when telegramUseSystemProxy is enabled', async () => {
|
||||||
|
const { config } = await import('../config.js');
|
||||||
|
(config as any).telegramEnabled = true;
|
||||||
|
(config as any).telegramBotToken = '123456:telegram-token';
|
||||||
|
(config as any).telegramChatId = '-1001234567890';
|
||||||
|
(config as any).telegramUseSystemProxy = true;
|
||||||
|
config.systemProxyUrl = 'http://127.0.0.1:7890';
|
||||||
|
config.smtpEnabled = false;
|
||||||
|
|
||||||
|
fetchMock.mockResolvedValue({ ok: true, status: 200 });
|
||||||
|
|
||||||
|
const { sendNotification } = await import('./notifyService.js');
|
||||||
|
await sendNotification('测试通知', 'proxy-test', 'info', { bypassThrottle: true, throwOnFailure: true });
|
||||||
|
|
||||||
|
expect(withExplicitProxyRequestInitMock).toHaveBeenCalledWith(
|
||||||
|
'http://127.0.0.1:7890',
|
||||||
|
expect.objectContaining({ method: 'POST' }),
|
||||||
|
);
|
||||||
|
expect(fetchMock).toHaveBeenCalledWith(
|
||||||
|
expect.stringContaining('/sendMessage'),
|
||||||
|
expect.objectContaining({ dispatcher: 'mock-proxy-dispatcher' }),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not apply proxy dispatcher when telegramUseSystemProxy is disabled', async () => {
|
||||||
|
const { config } = await import('../config.js');
|
||||||
|
(config as any).telegramEnabled = true;
|
||||||
|
(config as any).telegramBotToken = '123456:telegram-token';
|
||||||
|
(config as any).telegramChatId = '-1001234567890';
|
||||||
|
(config as any).telegramUseSystemProxy = false;
|
||||||
|
config.systemProxyUrl = 'http://127.0.0.1:7890';
|
||||||
|
config.smtpEnabled = false;
|
||||||
|
|
||||||
|
fetchMock.mockResolvedValue({ ok: true, status: 200 });
|
||||||
|
|
||||||
|
const { sendNotification } = await import('./notifyService.js');
|
||||||
|
await sendNotification('测试通知', 'no-proxy-test', 'info', { bypassThrottle: true, throwOnFailure: true });
|
||||||
|
|
||||||
|
expect(withExplicitProxyRequestInitMock).toHaveBeenCalledWith(
|
||||||
|
null,
|
||||||
|
expect.objectContaining({ method: 'POST' }),
|
||||||
|
);
|
||||||
|
const fetchOptions = fetchMock.mock.calls[0]?.[1] as Record<string, unknown>;
|
||||||
|
expect(fetchOptions.dispatcher).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { fetch } from 'undici';
|
import { fetch } from 'undici';
|
||||||
import { config } from '../config.js';
|
import { config } from '../config.js';
|
||||||
|
import { withExplicitProxyRequestInit } from './siteProxy.js';
|
||||||
import nodemailer, { type Transporter } from 'nodemailer';
|
import nodemailer, { type Transporter } from 'nodemailer';
|
||||||
import {
|
import {
|
||||||
createNotificationSignature,
|
createNotificationSignature,
|
||||||
@@ -224,15 +225,19 @@ export async function sendNotification(
|
|||||||
tasks.push({
|
tasks.push({
|
||||||
channel: 'telegram',
|
channel: 'telegram',
|
||||||
run: async () => {
|
run: async () => {
|
||||||
const response = await fetch(telegramApiUrl, {
|
const telegramRequestInit = withExplicitProxyRequestInit(
|
||||||
method: 'POST',
|
config.telegramUseSystemProxy ? config.systemProxyUrl : null,
|
||||||
headers: { 'Content-Type': 'application/json' },
|
{
|
||||||
body: JSON.stringify({
|
method: 'POST',
|
||||||
chat_id: config.telegramChatId,
|
headers: { 'Content-Type': 'application/json' },
|
||||||
text,
|
body: JSON.stringify({
|
||||||
disable_web_page_preview: true,
|
chat_id: config.telegramChatId,
|
||||||
}),
|
text,
|
||||||
});
|
disable_web_page_preview: true,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const response = await fetch(telegramApiUrl, telegramRequestInit);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`Telegram 响应状态 ${response.status}`);
|
throw new Error(`Telegram 响应状态 ${response.status}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ describe('NotificationSettings', () => {
|
|||||||
telegramApiBaseUrl: 'https://tg-proxy.example.com',
|
telegramApiBaseUrl: 'https://tg-proxy.example.com',
|
||||||
telegramChatId: '-1001234567890',
|
telegramChatId: '-1001234567890',
|
||||||
telegramBotTokenMasked: '1234****token',
|
telegramBotTokenMasked: '1234****token',
|
||||||
|
telegramUseSystemProxy: false,
|
||||||
smtpEnabled: false,
|
smtpEnabled: false,
|
||||||
smtpHost: '',
|
smtpHost: '',
|
||||||
smtpPort: 587,
|
smtpPort: 587,
|
||||||
@@ -105,4 +106,73 @@ describe('NotificationSettings', () => {
|
|||||||
root?.unmount();
|
root?.unmount();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('loads and saves telegram use system proxy toggle', async () => {
|
||||||
|
apiMock.getRuntimeSettings.mockResolvedValue({
|
||||||
|
webhookUrl: '',
|
||||||
|
barkUrl: '',
|
||||||
|
webhookEnabled: true,
|
||||||
|
barkEnabled: true,
|
||||||
|
serverChanEnabled: false,
|
||||||
|
telegramEnabled: true,
|
||||||
|
telegramApiBaseUrl: 'https://api.telegram.org',
|
||||||
|
telegramChatId: '-1001234567890',
|
||||||
|
telegramBotTokenMasked: '1234****token',
|
||||||
|
telegramUseSystemProxy: false,
|
||||||
|
smtpEnabled: false,
|
||||||
|
smtpHost: '',
|
||||||
|
smtpPort: 587,
|
||||||
|
smtpSecure: false,
|
||||||
|
smtpUser: '',
|
||||||
|
smtpFrom: '',
|
||||||
|
smtpTo: '',
|
||||||
|
notifyCooldownSec: 300,
|
||||||
|
});
|
||||||
|
|
||||||
|
let root: ReturnType<typeof create> | null = null;
|
||||||
|
try {
|
||||||
|
await act(async () => {
|
||||||
|
root = create(
|
||||||
|
<MemoryRouter>
|
||||||
|
<ToastProvider>
|
||||||
|
<NotificationSettings />
|
||||||
|
</ToastProvider>
|
||||||
|
</MemoryRouter>,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
await flushMicrotasks();
|
||||||
|
|
||||||
|
const allCheckboxes = root.root.findAll((node) => (
|
||||||
|
node.type === 'input' && node.props.type === 'checkbox'
|
||||||
|
));
|
||||||
|
const proxyCheckbox = allCheckboxes.find((node) => {
|
||||||
|
const parent = node.parent;
|
||||||
|
if (!parent) return false;
|
||||||
|
const text = collectText(parent);
|
||||||
|
return text.includes('使用系统代理');
|
||||||
|
});
|
||||||
|
expect(proxyCheckbox).toBeTruthy();
|
||||||
|
expect(proxyCheckbox!.props.checked).toBe(false);
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
proxyCheckbox!.props.onChange({ target: { checked: true } });
|
||||||
|
});
|
||||||
|
|
||||||
|
const saveButton = root.root.find((node) => (
|
||||||
|
node.type === 'button'
|
||||||
|
&& typeof node.props.onClick === 'function'
|
||||||
|
&& collectText(node).includes('保存通知设置')
|
||||||
|
));
|
||||||
|
await act(async () => {
|
||||||
|
saveButton.props.onClick();
|
||||||
|
});
|
||||||
|
await flushMicrotasks();
|
||||||
|
|
||||||
|
expect(apiMock.updateRuntimeSettings).toHaveBeenCalledWith(expect.objectContaining({
|
||||||
|
telegramUseSystemProxy: true,
|
||||||
|
}));
|
||||||
|
} finally {
|
||||||
|
root?.unmount();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ type RuntimeSettings = {
|
|||||||
telegramEnabled: boolean;
|
telegramEnabled: boolean;
|
||||||
telegramApiBaseUrl: string;
|
telegramApiBaseUrl: string;
|
||||||
telegramChatId: string;
|
telegramChatId: string;
|
||||||
|
telegramUseSystemProxy: boolean;
|
||||||
smtpEnabled: boolean;
|
smtpEnabled: boolean;
|
||||||
smtpHost: string;
|
smtpHost: string;
|
||||||
smtpPort: number;
|
smtpPort: number;
|
||||||
@@ -35,6 +36,7 @@ export default function NotificationSettings() {
|
|||||||
telegramEnabled: false,
|
telegramEnabled: false,
|
||||||
telegramApiBaseUrl: 'https://api.telegram.org',
|
telegramApiBaseUrl: 'https://api.telegram.org',
|
||||||
telegramChatId: '',
|
telegramChatId: '',
|
||||||
|
telegramUseSystemProxy: false,
|
||||||
smtpEnabled: false,
|
smtpEnabled: false,
|
||||||
smtpHost: '',
|
smtpHost: '',
|
||||||
smtpPort: 587,
|
smtpPort: 587,
|
||||||
@@ -78,6 +80,7 @@ export default function NotificationSettings() {
|
|||||||
telegramEnabled: !!runtimeInfo.telegramEnabled,
|
telegramEnabled: !!runtimeInfo.telegramEnabled,
|
||||||
telegramApiBaseUrl: runtimeInfo.telegramApiBaseUrl || 'https://api.telegram.org',
|
telegramApiBaseUrl: runtimeInfo.telegramApiBaseUrl || 'https://api.telegram.org',
|
||||||
telegramChatId: runtimeInfo.telegramChatId || '',
|
telegramChatId: runtimeInfo.telegramChatId || '',
|
||||||
|
telegramUseSystemProxy: !!runtimeInfo.telegramUseSystemProxy,
|
||||||
smtpEnabled: !!runtimeInfo.smtpEnabled,
|
smtpEnabled: !!runtimeInfo.smtpEnabled,
|
||||||
smtpHost: runtimeInfo.smtpHost || '',
|
smtpHost: runtimeInfo.smtpHost || '',
|
||||||
smtpPort: Number(runtimeInfo.smtpPort) || 587,
|
smtpPort: Number(runtimeInfo.smtpPort) || 587,
|
||||||
@@ -115,6 +118,7 @@ export default function NotificationSettings() {
|
|||||||
telegramEnabled: runtime.telegramEnabled,
|
telegramEnabled: runtime.telegramEnabled,
|
||||||
telegramApiBaseUrl: runtime.telegramApiBaseUrl,
|
telegramApiBaseUrl: runtime.telegramApiBaseUrl,
|
||||||
telegramChatId: runtime.telegramChatId,
|
telegramChatId: runtime.telegramChatId,
|
||||||
|
telegramUseSystemProxy: runtime.telegramUseSystemProxy,
|
||||||
smtpEnabled: runtime.smtpEnabled,
|
smtpEnabled: runtime.smtpEnabled,
|
||||||
smtpHost: runtime.smtpHost,
|
smtpHost: runtime.smtpHost,
|
||||||
smtpPort: runtime.smtpPort,
|
smtpPort: runtime.smtpPort,
|
||||||
@@ -317,15 +321,26 @@ export default function NotificationSettings() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label style={{ display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer' }}>
|
<div style={{ display: 'flex', gap: 16 }}>
|
||||||
<span style={{ fontSize: 13, fontWeight: 500, color: runtime.telegramEnabled ? 'var(--color-primary)' : 'var(--color-text-muted)' }}>启用 Telegram</span>
|
<label style={{ display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer' }}>
|
||||||
<input
|
<span style={{ fontSize: 13, fontWeight: 500, color: runtime.telegramUseSystemProxy ? 'var(--color-primary)' : 'var(--color-text-muted)' }}>使用系统代理</span>
|
||||||
type="checkbox"
|
<input
|
||||||
style={{ width: 16, height: 16, cursor: 'pointer' }}
|
type="checkbox"
|
||||||
checked={runtime.telegramEnabled}
|
style={{ width: 16, height: 16, cursor: 'pointer' }}
|
||||||
onChange={(e) => setRuntime((prev) => ({ ...prev, telegramEnabled: e.target.checked }))}
|
checked={runtime.telegramUseSystemProxy}
|
||||||
/>
|
onChange={(e) => setRuntime((prev) => ({ ...prev, telegramUseSystemProxy: e.target.checked }))}
|
||||||
</label>
|
/>
|
||||||
|
</label>
|
||||||
|
<label style={{ display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer' }}>
|
||||||
|
<span style={{ fontSize: 13, fontWeight: 500, color: runtime.telegramEnabled ? 'var(--color-primary)' : 'var(--color-text-muted)' }}>启用 Telegram</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
style={{ width: 16, height: 16, cursor: 'pointer' }}
|
||||||
|
checked={runtime.telegramEnabled}
|
||||||
|
onChange={(e) => setRuntime((prev) => ({ ...prev, telegramEnabled: e.target.checked }))}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(0, 1fr)', gap: '16px 20px', opacity: runtime.telegramEnabled ? 1 : 0.6, transition: 'opacity 0.2s' }}>
|
<div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(0, 1fr)', gap: '16px 20px', opacity: runtime.telegramEnabled ? 1 : 0.6, transition: 'opacity 0.2s' }}>
|
||||||
|
|||||||
Reference in New Issue
Block a user