feat(xray): preview export in a modal and switch rule enable toggle

Routing and Outbounds export now opens a TextModal showing the JSON with
copy/download buttons instead of auto-downloading the file. Routing import
and export are collapsed into a "More" dropdown to match the Outbounds tab.
The rule form Enabled field becomes a Switch instead of an Enabled/Disabled
Select.
This commit is contained in:
MHSanaei
2026-06-21 16:29:46 +02:00
parent 7c8889466b
commit 97c02ef69f
3 changed files with 43 additions and 26 deletions
+25 -14
View File
@@ -1,18 +1,19 @@
import { useCallback, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Button, Modal, Space, Table, Tabs, message } from 'antd';
import { Button, Dropdown, Modal, Space, Table, Tabs, message } from 'antd';
import {
AimOutlined,
ControlOutlined,
ExportOutlined,
ImportOutlined,
MoreOutlined,
PlusOutlined,
UnorderedListOutlined,
} from '@ant-design/icons';
import { catTabLabel } from '@/pages/settings/catTabLabel';
import { FileManager } from '@/utils';
import PromptModal from '@/components/feedback/PromptModal';
import TextModal from '@/components/feedback/TextModal';
import RoutingBasic from './RoutingBasic';
import RouteTester from './RouteTester';
import RuleFormModal from './RuleFormModal';
@@ -144,11 +145,12 @@ export default function RoutingTab({
}, [templateSettings?.routing?.balancers]);
const [importOpen, setImportOpen] = useState(false);
const [exportOpen, setExportOpen] = useState(false);
const [exportContent, setExportContent] = useState('');
function exportRules() {
FileManager.downloadTextFile(JSON.stringify(rules, null, 2), 'routing-rules.json', {
type: 'application/json',
});
setExportContent(JSON.stringify(rules, null, 2));
setExportOpen(true);
}
function importRules(value: string) {
@@ -333,16 +335,17 @@ export default function RoutingTab({
<Button type="primary" icon={<PlusOutlined />} onClick={openAdd}>
{t('pages.xray.Routings')}
</Button>
<Button icon={<ImportOutlined />} onClick={() => setImportOpen(true)}>
{t('pages.xray.importRules')}
</Button>
<Button
icon={<ExportOutlined />}
onClick={exportRules}
disabled={rules.length === 0}
<Dropdown
trigger={['click']}
menu={{
items: [
{ key: 'import', icon: <ImportOutlined />, label: t('pages.xray.importRules'), onClick: () => setImportOpen(true) },
{ key: 'export', icon: <ExportOutlined />, label: t('pages.xray.exportRules'), disabled: rules.length === 0, onClick: exportRules },
],
}}
>
{t('pages.xray.exportRules')}
</Button>
<Button icon={<MoreOutlined />}>{t('more')}</Button>
</Dropdown>
</Space>
{isMobile ? (
@@ -405,6 +408,14 @@ export default function RoutingTab({
json
onConfirm={importRules}
/>
<TextModal
open={exportOpen}
onClose={() => setExportOpen(false)}
title={t('pages.xray.exportRules')}
content={exportContent}
fileName="routing-rules.json"
json
/>
</>
);
}