From 96b3d862ca7d8ca25591605fd7d0baeb4c0e793e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=A8=E9=9B=AA?= Date: Tue, 18 Aug 2026 09:05:18 +0800 Subject: [PATCH] ui(listeners): restore single-page create/edit form (remove wizard) ui(listeners): restore single-page create/edit form (remove wizard) ui(listeners): restore single-page create/edit form (remove wizard) ui(listeners): restore single-page create/edit form (remove wizard) ui(listeners): restore single-page create/edit form (remove wizard) ui(listeners): restore single-page create/edit form (remove wizard) ui(listeners): restore single-page create/edit form (remove wizard) ui(listeners): restore single-page create/edit form (remove wizard) ui(listeners): restore single-page create/edit form (remove wizard) ui(listeners): restore single-page create/edit form (remove wizard) ui(listeners): restore single-page create/edit form (remove wizard) ui(listeners): restore single-page create/edit form (remove wizard) --- frontend/src/pages/Listeners.tsx | 179 +++++++++++-------------------- 1 file changed, 63 insertions(+), 116 deletions(-) diff --git a/frontend/src/pages/Listeners.tsx b/frontend/src/pages/Listeners.tsx index 4746f62..b2be587 100644 --- a/frontend/src/pages/Listeners.tsx +++ b/frontend/src/pages/Listeners.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react'; -import { Table, Button, Space, Tag, Modal, Form, Input, Select, Switch, message, Popconfirm, Tooltip, Card, Tabs, Descriptions, Divider, Steps } from 'antd'; +import { Table, Button, Space, Tag, Modal, Form, Input, Select, Switch, message, Popconfirm, Tooltip, Card, Tabs, Descriptions, Divider } from 'antd'; import { PlusOutlined, ReloadOutlined, QrcodeOutlined, DeleteOutlined, EditOutlined, CopyOutlined, BranchesOutlined, HistoryOutlined, SaveOutlined, PoweroffOutlined, DiffOutlined } from '@ant-design/icons'; import { fetchListeners, createListener, updateListener, deleteListener, reloadListener, exportNodeURI, normalizeId, Listener, @@ -45,7 +45,6 @@ const Listeners: React.FC = () => { const [diffText, setDiffText] = useState(''); const [selectedRowKeys, setSelectedRowKeys] = useState([]); const protocol = Form.useWatch('protocol', form); - const [wizardStep, setWizardStep] = useState(0); const load = async () => { setLoading(true); @@ -59,31 +58,26 @@ const Listeners: React.FC = () => { const openCreate = () => { setEditing(null); - setWizardStep(0); form.resetFields(); form.setFieldsValue({ bind_address: '0.0.0.0', enabled: true, udp: false, protocol: 'vless' }); setModalOpen(true); }; const openEdit = (record: Listener) => { setEditing(record); - setWizardStep(0); form.resetFields(); form.setFieldsValue({ name: record.name, protocol: record.protocol, port: record.port, bind_address: record.bind_address || '0.0.0.0', enabled: record.enabled, udp: record.udp, ...configToFormValues(record.config) }); setModalOpen(true); }; const onSubmit = async (rawValues?: any) => { try { - // Wizard unmounts prior steps; always read full store (including preserved fields). const values = { ...(form.getFieldsValue(true) || {}), ...(rawValues || {}) }; const proto = String(values.protocol || '').trim(); if (!proto) { message.error(t('listeners.selectProtocolFirst')); - setWizardStep(0); return; } if (!values.name || !String(values.port || '').trim()) { message.error(t('listeners.portHint') || 'Name and port are required'); - setWizardStep(0); return; } const previous = editing ? parseConfig(editing.config) : null; @@ -97,10 +91,20 @@ const Listeners: React.FC = () => { udp: protocolSupportsUDP(proto) ? !!values.udp : false, config: JSON.stringify(config), }; - if (editing) { await updateListener(normalizeId(editing), payload); message.success(t('listeners.updated')); } - else { await createListener(payload); message.success(t('listeners.created')); } - setModalOpen(false); setEditing(null); setWizardStep(0); form.resetFields(); await load(); - } catch (e: any) { message.error(e.message); } + if (editing) { + await updateListener(normalizeId(editing), payload); + message.success(t('listeners.updated')); + } else { + await createListener(payload); + message.success(t('listeners.created')); + } + setModalOpen(false); + setEditing(null); + form.resetFields(); + await load(); + } catch (e: any) { + message.error(e.message); + } }; const onDelete = async (id: number) => { try { await deleteListener(id); message.success(t('listeners.deleted')); await load(); } catch (e: any) { message.error(e.message); } }; const onReload = async (id: number) => { try { await reloadListener(id); message.success(t('listeners.reloaded')); await load(); } catch (e: any) { message.error(e.message); } }; @@ -187,116 +191,59 @@ const Listeners: React.FC = () => { { setModalOpen(false); setEditing(null); setWizardStep(0); form.resetFields(); }} - width={typeof window !== 'undefined' && window.innerWidth < 768 ? '100%' : 760} + title={editing ? t('listeners.edit') : t('listeners.create')} + onCancel={() => { setModalOpen(false); setEditing(null); form.resetFields(); }} + onOk={() => form.submit()} + width={typeof window !== 'undefined' && window.innerWidth < 768 ? '100%' : 720} destroyOnClose styles={{ body: { maxHeight: '70vh', overflowY: 'auto' } }} - footer={ - editing ? ( - - - - - ) : ( - - - {wizardStep > 0 && ( - - )} - {wizardStep < 2 ? ( - - ) : ( - - )} - - ) - } > - {!editing && ( - - )}
- {(editing || wizardStep === 0) && ( - <> - - - - - - {protocolSupportsUDP(protocol) && } - - )} - {(editing || wizardStep === 1) && ( -
- {!editing && wizardStep === 1 && ( -

- {t('listeners.wizardConfigHint') || 'Configure protocol-specific fields (TLS / Reality / users, etc.).'} -

- )} - -
- )} - {!editing && wizardStep === 2 && ( - - {form.getFieldValue('name') || '-'} - {form.getFieldValue('protocol') || '-'} - {form.getFieldValue('port') || '-'} - {form.getFieldValue('bind_address') || '0.0.0.0'} - {form.getFieldValue('enabled') ? t('common.enabled') : t('common.disabled')} - {protocolSupportsUDP(protocol) && ( - {form.getFieldValue('udp') ? 'UDP' : '-'} - )} - -
-                {JSON.stringify(formValuesToConfig(form.getFieldValue('protocol') || protocol, form.getFieldsValue(true), null), null, 2)}
-              
-
-
+ + + + + + + + + + + + + {protocolSupportsUDP(protocol) && ( + + + )} +