mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-11 15:16:07 +00:00
refactor(frontend): move form-item hints from extra to tooltip
Switch reality target, node options, and WARP auto-update-IP hints from inline extra text to label tooltips for a cleaner form layout.
This commit is contained in:
@@ -47,7 +47,7 @@ export default function RealityForm({
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('pages.inbounds.form.target')}
|
||||
extra={t('pages.inbounds.form.realityTargetHint')}
|
||||
tooltip={t('pages.inbounds.form.realityTargetHint')}
|
||||
>
|
||||
<Space.Compact block>
|
||||
<Form.Item
|
||||
|
||||
@@ -323,7 +323,7 @@ export default function NodeFormModal({
|
||||
label={t('pages.nodes.allowPrivateAddress')}
|
||||
name="allowPrivateAddress"
|
||||
valuePropName="checked"
|
||||
extra={t('pages.nodes.allowPrivateAddressHint')}
|
||||
tooltip={t('pages.nodes.allowPrivateAddressHint')}
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
@@ -331,7 +331,7 @@ export default function NodeFormModal({
|
||||
<Form.Item
|
||||
label={t('pages.nodes.tlsVerifyMode')}
|
||||
name="tlsVerifyMode"
|
||||
extra={t('pages.nodes.tlsVerifyModeHint')}
|
||||
tooltip={t('pages.nodes.tlsVerifyModeHint')}
|
||||
>
|
||||
<Select
|
||||
disabled={scheme === 'http'}
|
||||
@@ -366,7 +366,7 @@ export default function NodeFormModal({
|
||||
<Form.Item
|
||||
label={t('pages.nodes.pinnedCert')}
|
||||
name="pinnedCertSha256"
|
||||
extra={t('pages.nodes.pinnedCertHint')}
|
||||
tooltip={t('pages.nodes.pinnedCertHint')}
|
||||
>
|
||||
<Input.Search
|
||||
placeholder={t('pages.nodes.pinnedCertPlaceholder')}
|
||||
@@ -381,7 +381,7 @@ export default function NodeFormModal({
|
||||
label={t('pages.nodes.apiToken')}
|
||||
name="apiToken"
|
||||
rules={[antdRule(NodeFormSchema.shape.apiToken, t)]}
|
||||
extra={t('pages.nodes.apiTokenHint')}
|
||||
tooltip={t('pages.nodes.apiTokenHint')}
|
||||
>
|
||||
<Input.Password placeholder={t('pages.nodes.apiTokenPlaceholder')} />
|
||||
</Form.Item>
|
||||
@@ -389,7 +389,7 @@ export default function NodeFormModal({
|
||||
<Form.Item
|
||||
label={t('pages.nodes.outboundTag')}
|
||||
name="outboundTag"
|
||||
extra={t('pages.nodes.outboundTagHint')}
|
||||
tooltip={t('pages.nodes.outboundTagHint')}
|
||||
getValueProps={(v) => ({ value: (v as string) || undefined })}
|
||||
>
|
||||
<Select
|
||||
@@ -403,7 +403,7 @@ export default function NodeFormModal({
|
||||
<Form.Item
|
||||
label={t('pages.nodes.inboundSyncMode')}
|
||||
name="inboundSyncMode"
|
||||
extra={t('pages.nodes.inboundSyncModeHint')}
|
||||
tooltip={t('pages.nodes.inboundSyncModeHint')}
|
||||
>
|
||||
<Select
|
||||
options={[
|
||||
@@ -417,7 +417,7 @@ export default function NodeFormModal({
|
||||
<Form.Item
|
||||
label={t('pages.nodes.inboundTags')}
|
||||
name="inboundTags"
|
||||
extra={t('pages.nodes.inboundTagsHint')}
|
||||
tooltip={t('pages.nodes.inboundTagsHint')}
|
||||
>
|
||||
<Select
|
||||
mode="multiple"
|
||||
|
||||
@@ -266,170 +266,171 @@ export default function WarpModal({
|
||||
<>
|
||||
{messageContextHolder}
|
||||
<Modal open={open} title="Cloudflare WARP" footer={null} onCancel={onClose}>
|
||||
{!hasWarp ? (
|
||||
<Button type="primary" loading={loading} icon={<ApiOutlined />} onClick={register}>
|
||||
{t('pages.xray.warp.createAccount')}
|
||||
</Button>
|
||||
) : (
|
||||
<>
|
||||
<table className="warp-data-table">
|
||||
<tbody>
|
||||
<tr className="row-odd">
|
||||
<td>{t('pages.xray.warp.accessToken')}</td>
|
||||
<td>{warpData?.access_token}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{t('pages.xray.warp.deviceId')}</td>
|
||||
<td>{warpData?.device_id}</td>
|
||||
</tr>
|
||||
<tr className="row-odd">
|
||||
<td>{t('pages.xray.warp.licenseKey')}</td>
|
||||
<td>{warpData?.license_key}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{t('pages.xray.warp.privateKey')}</td>
|
||||
<td>{warpData?.private_key}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<Button loading={loading} type="primary" danger className="mt-8" icon={<DeleteOutlined />} onClick={delConfig}>
|
||||
{t('pages.xray.warp.deleteAccount')}
|
||||
{!hasWarp ? (
|
||||
<Button type="primary" loading={loading} icon={<ApiOutlined />} onClick={register}>
|
||||
{t('pages.xray.warp.createAccount')}
|
||||
</Button>
|
||||
) : (
|
||||
<>
|
||||
<table className="warp-data-table">
|
||||
<tbody>
|
||||
<tr className="row-odd">
|
||||
<td>{t('pages.xray.warp.accessToken')}</td>
|
||||
<td>{warpData?.access_token}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{t('pages.xray.warp.deviceId')}</td>
|
||||
<td>{warpData?.device_id}</td>
|
||||
</tr>
|
||||
<tr className="row-odd">
|
||||
<td>{t('pages.xray.warp.licenseKey')}</td>
|
||||
<td>{warpData?.license_key}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{t('pages.xray.warp.privateKey')}</td>
|
||||
<td>{warpData?.private_key}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<Divider className="zero-margin">{t('pages.xray.warp.settings')}</Divider>
|
||||
<Button loading={loading} type="primary" danger className="mt-8" icon={<DeleteOutlined />} onClick={delConfig}>
|
||||
{t('pages.xray.warp.deleteAccount')}
|
||||
</Button>
|
||||
|
||||
<Collapse
|
||||
className="my-10"
|
||||
items={[
|
||||
{
|
||||
key: '1',
|
||||
label: t('pages.xray.warp.licenseKeyLabel'),
|
||||
children: (
|
||||
<Form colon={false} labelCol={{ md: { span: 6 } }} wrapperCol={{ md: { span: 14 } }}>
|
||||
<Form.Item label={t('pages.xray.warp.key')}>
|
||||
<Input
|
||||
value={warpPlus}
|
||||
placeholder={t('pages.xray.warp.keyPlaceholder')}
|
||||
onChange={(e) => {
|
||||
setWarpPlus(e.target.value);
|
||||
setLicenseError('');
|
||||
}}
|
||||
/>
|
||||
<div className="license-actions mt-8">
|
||||
<Button
|
||||
type="primary"
|
||||
disabled={warpPlus.length < 26}
|
||||
loading={loading}
|
||||
onClick={updateLicense}
|
||||
>
|
||||
{t('update')}
|
||||
<Divider className="zero-margin">{t('pages.xray.warp.settings')}</Divider>
|
||||
|
||||
<Collapse
|
||||
className="my-10"
|
||||
items={[
|
||||
{
|
||||
key: '1',
|
||||
label: t('pages.xray.warp.licenseKeyLabel'),
|
||||
children: (
|
||||
<Form colon={false} labelCol={{ md: { span: 6 } }} wrapperCol={{ md: { span: 14 } }}>
|
||||
<Form.Item label={t('pages.xray.warp.key')}>
|
||||
<Input
|
||||
value={warpPlus}
|
||||
placeholder={t('pages.xray.warp.keyPlaceholder')}
|
||||
onChange={(e) => {
|
||||
setWarpPlus(e.target.value);
|
||||
setLicenseError('');
|
||||
}}
|
||||
/>
|
||||
<div className="license-actions mt-8">
|
||||
<Button
|
||||
type="primary"
|
||||
disabled={warpPlus.length < 26}
|
||||
loading={loading}
|
||||
onClick={updateLicense}
|
||||
>
|
||||
{t('update')}
|
||||
</Button>
|
||||
{licenseError && (
|
||||
<Alert title={licenseError} type="error" showIcon className="license-error" />
|
||||
)}
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: t('pages.xray.warp.autoUpdateIp', 'Auto Update IP Address'),
|
||||
children: (
|
||||
<Form colon={false} labelCol={{ md: { span: 8 } }} wrapperCol={{ md: { span: 12 } }}>
|
||||
<Form.Item label={t('pages.xray.warp.intervalDays', 'Interval (Days)')}
|
||||
tooltip={t('pages.xray.warp.intervalDesc', '0 to disable. Changes IP address automatically.')}>
|
||||
<Input
|
||||
type="number"
|
||||
min={0}
|
||||
value={updateInterval}
|
||||
onChange={(e) => setUpdateInterval(Number(e.target.value))}
|
||||
/>
|
||||
<Button className="mt-8" type="primary" loading={loading} onClick={saveInterval}>
|
||||
{t('save', 'Save')}
|
||||
</Button>
|
||||
{licenseError && (
|
||||
<Alert title={licenseError} type="error" showIcon className="license-error" />
|
||||
)}
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: t('pages.xray.warp.autoUpdateIp', 'Auto Update IP Address'),
|
||||
children: (
|
||||
<Form colon={false} labelCol={{ md: { span: 8 } }} wrapperCol={{ md: { span: 12 } }}>
|
||||
<Form.Item label={t('pages.xray.warp.intervalDays', 'Interval (Days)')} extra={t('pages.xray.warp.intervalDesc', '0 to disable. Changes IP address automatically.')}>
|
||||
<Input
|
||||
type="number"
|
||||
min={0}
|
||||
value={updateInterval}
|
||||
onChange={(e) => setUpdateInterval(Number(e.target.value))}
|
||||
/>
|
||||
<Button className="mt-8" type="primary" loading={loading} onClick={saveInterval}>
|
||||
{t('save', 'Save')}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<Divider className="zero-margin">{t('pages.xray.warp.accountInfo')}</Divider>
|
||||
<div className="my-8">
|
||||
<Button loading={loading} type="primary" icon={<SyncOutlined />} onClick={getConfig}>
|
||||
{t('refresh')}
|
||||
</Button>
|
||||
<Button loading={loading} type="primary" className="ml-8" icon={<SyncOutlined />} onClick={changeIp}>
|
||||
{t('pages.xray.warp.changeIp', 'Change IP')}
|
||||
</Button>
|
||||
</div>
|
||||
<Divider className="zero-margin">{t('pages.xray.warp.accountInfo')}</Divider>
|
||||
<div className="my-8">
|
||||
<Button loading={loading} type="primary" icon={<SyncOutlined />} onClick={getConfig}>
|
||||
{t('refresh')}
|
||||
</Button>
|
||||
<Button loading={loading} type="primary" className="ml-8" icon={<SyncOutlined />} onClick={changeIp}>
|
||||
{t('pages.xray.warp.changeIp', 'Change IP')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{hasConfig && (
|
||||
<>
|
||||
<table className="warp-data-table">
|
||||
<tbody>
|
||||
<tr className="row-odd">
|
||||
<td>{t('pages.xray.warp.deviceName')}</td>
|
||||
<td>{warpConfig?.name}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{t('pages.xray.warp.deviceModel')}</td>
|
||||
<td>{warpConfig?.model}</td>
|
||||
</tr>
|
||||
<tr className="row-odd">
|
||||
<td>{t('pages.xray.warp.deviceEnabled')}</td>
|
||||
<td>{String(warpConfig?.enabled)}</td>
|
||||
</tr>
|
||||
{warpConfig?.account && (
|
||||
<>
|
||||
<tr>
|
||||
<td>{t('pages.xray.warp.accountType')}</td>
|
||||
<td>{warpConfig.account.account_type}</td>
|
||||
</tr>
|
||||
<tr className="row-odd">
|
||||
<td>{t('pages.xray.warp.role')}</td>
|
||||
<td>{warpConfig.account.role}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{t('pages.xray.warp.warpPlusData')}</td>
|
||||
<td>{SizeFormatter.sizeFormat(warpConfig.account.premium_data)}</td>
|
||||
</tr>
|
||||
<tr className="row-odd">
|
||||
<td>{t('pages.xray.warp.quota')}</td>
|
||||
<td>{SizeFormatter.sizeFormat(warpConfig.account.quota)}</td>
|
||||
</tr>
|
||||
{warpConfig.account.usage != null && (
|
||||
{hasConfig && (
|
||||
<>
|
||||
<table className="warp-data-table">
|
||||
<tbody>
|
||||
<tr className="row-odd">
|
||||
<td>{t('pages.xray.warp.deviceName')}</td>
|
||||
<td>{warpConfig?.name}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{t('pages.xray.warp.deviceModel')}</td>
|
||||
<td>{warpConfig?.model}</td>
|
||||
</tr>
|
||||
<tr className="row-odd">
|
||||
<td>{t('pages.xray.warp.deviceEnabled')}</td>
|
||||
<td>{String(warpConfig?.enabled)}</td>
|
||||
</tr>
|
||||
{warpConfig?.account && (
|
||||
<>
|
||||
<tr>
|
||||
<td>{t('pages.xray.warp.usage')}</td>
|
||||
<td>{SizeFormatter.sizeFormat(warpConfig.account.usage)}</td>
|
||||
<td>{t('pages.xray.warp.accountType')}</td>
|
||||
<td>{warpConfig.account.account_type}</td>
|
||||
</tr>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
<tr className="row-odd">
|
||||
<td>{t('pages.xray.warp.role')}</td>
|
||||
<td>{warpConfig.account.role}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{t('pages.xray.warp.warpPlusData')}</td>
|
||||
<td>{SizeFormatter.sizeFormat(warpConfig.account.premium_data)}</td>
|
||||
</tr>
|
||||
<tr className="row-odd">
|
||||
<td>{t('pages.xray.warp.quota')}</td>
|
||||
<td>{SizeFormatter.sizeFormat(warpConfig.account.quota)}</td>
|
||||
</tr>
|
||||
{warpConfig.account.usage != null && (
|
||||
<tr>
|
||||
<td>{t('pages.xray.warp.usage')}</td>
|
||||
<td>{SizeFormatter.sizeFormat(warpConfig.account.usage)}</td>
|
||||
</tr>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<Divider className="my-10">{t('pages.xray.outbound.outboundStatus')}</Divider>
|
||||
{warpOutboundIndex >= 0 ? (
|
||||
<>
|
||||
<Tag color="green">{t('enabled')}</Tag>
|
||||
<Button type="primary" danger loading={loading} className="ml-8" onClick={resetOutbound}>
|
||||
{t('reset')}
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Tag color="orange">{t('disabled')}</Tag>
|
||||
<Button type="primary" loading={loading} className="ml-8" icon={<PlusOutlined />} onClick={addOutbound}>
|
||||
{t('pages.xray.warp.addOutbound')}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<Divider className="my-10">{t('pages.xray.outbound.outboundStatus')}</Divider>
|
||||
{warpOutboundIndex >= 0 ? (
|
||||
<>
|
||||
<Tag color="green">{t('enabled')}</Tag>
|
||||
<Button type="primary" danger loading={loading} className="ml-8" onClick={resetOutbound}>
|
||||
{t('reset')}
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Tag color="orange">{t('disabled')}</Tag>
|
||||
<Button type="primary" loading={loading} className="ml-8" icon={<PlusOutlined />} onClick={addOutbound}>
|
||||
{t('pages.xray.warp.addOutbound')}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user