feat: add port enable/disable & random port

* Support random port

* feat: add port enable/disable
This commit is contained in:
Memory 2025-11-13 20:22:18 +08:00 committed by GitHub
parent 8ebe99a8ca
commit 9a0eb26ef2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 222 additions and 31 deletions

View File

@ -44,7 +44,17 @@ export const defaultConfig: IAppConfig = {
], ],
siderWidth: 250, siderWidth: 250,
sysProxy: { enable: false, mode: 'manual' }, sysProxy: { enable: false, mode: 'manual' },
triggerMainWindowBehavior: 'show' // 添加默认值 triggerMainWindowBehavior: 'show',
showMixedPort: 7890,
enableMixedPort: true,
showSocksPort: 7891,
enableSocksPort: true,
showHttpPort: 7892,
enableHttpPort: true,
showRedirPort: 0,
enableRedirPort: false,
showTproxyPort: 0,
enableTproxyPort: false
} }
export const defaultControledMihomoConfig: Partial<IMihomoConfig> = { export const defaultControledMihomoConfig: Partial<IMihomoConfig> = {

View File

@ -6,7 +6,7 @@ import { useAppConfig } from '@renderer/hooks/use-app-config'
import { useControledMihomoConfig } from '@renderer/hooks/use-controled-mihomo-config' import { useControledMihomoConfig } from '@renderer/hooks/use-controled-mihomo-config'
import { platform } from '@renderer/utils/init' import { platform } from '@renderer/utils/init'
import { FaNetworkWired } from 'react-icons/fa' import { FaNetworkWired } from 'react-icons/fa'
import { IoMdCloudDownload, IoMdInformationCircleOutline, IoMdRefresh } from 'react-icons/io' import { IoMdCloudDownload, IoMdInformationCircleOutline, IoMdRefresh, IoMdShuffle } from 'react-icons/io'
import PubSub from 'pubsub-js' import PubSub from 'pubsub-js'
import { import {
mihomoUpgrade, mihomoUpgrade,
@ -42,7 +42,21 @@ const Mihomo: React.FC = () => {
smartCoreCollectData = false, smartCoreCollectData = false,
smartCoreStrategy = 'sticky-sessions', smartCoreStrategy = 'sticky-sessions',
maxLogDays = 7, maxLogDays = 7,
sysProxy sysProxy,
disableLoopbackDetector,
disableEmbedCA,
disableSystemCA,
skipSafePathCheck,
showMixedPort,
enableMixedPort = true,
showSocksPort,
enableSocksPort = true,
showHttpPort,
enableHttpPort = true,
showRedirPort,
enableRedirPort = false,
showTproxyPort,
enableTproxyPort = false
} = appConfig || {} } = appConfig || {}
const { controledMihomoConfig, patchControledMihomoConfig } = useControledMihomoConfig() const { controledMihomoConfig, patchControledMihomoConfig } = useControledMihomoConfig()
@ -75,11 +89,12 @@ const Mihomo: React.FC = () => {
} = controledMihomoConfig || {} } = controledMihomoConfig || {}
const { 'store-selected': storeSelected, 'store-fake-ip': storeFakeIp } = profile const { 'store-selected': storeSelected, 'store-fake-ip': storeFakeIp } = profile
const [mixedPortInput, setMixedPortInput] = useState(mixedPort) const [isManualPortChange, setIsManualPortChange] = useState(false)
const [socksPortInput, setSocksPortInput] = useState(socksPort) const [mixedPortInput, setMixedPortInput] = useState(showMixedPort || mixedPort)
const [httpPortInput, setHttpPortInput] = useState(httpPort) const [socksPortInput, setSocksPortInput] = useState(showSocksPort || socksPort)
const [redirPortInput, setRedirPortInput] = useState(redirPort) const [httpPortInput, setHttpPortInput] = useState(showHttpPort || httpPort)
const [tproxyPortInput, setTproxyPortInput] = useState(tproxyPort) const [redirPortInput, setRedirPortInput] = useState(showRedirPort || redirPort)
const [tproxyPortInput, setTproxyPortInput] = useState(showTproxyPort || tproxyPort)
const [externalControllerInput, setExternalControllerInput] = useState(externalController) const [externalControllerInput, setExternalControllerInput] = useState(externalController)
const [secretInput, setSecretInput] = useState(secret) const [secretInput, setSecretInput] = useState(secret)
const [lanAllowedIpsInput, setLanAllowedIpsInput] = useState(lanAllowedIps) const [lanAllowedIpsInput, setLanAllowedIpsInput] = useState(lanAllowedIps)
@ -116,6 +131,9 @@ const Mihomo: React.FC = () => {
const { host, port } = parseController() const { host, port } = parseController()
// 生成随机端口(范围1024-65535)
const generateRandomPort = () => Math.floor(Math.random() * (65535 - 1024 + 1)) + 1024
// 默认WebUI面板选项 // 默认WebUI面板选项
const defaultWebUIPanels: WebUIPanel[] = [ const defaultWebUIPanels: WebUIPanel[] = [
{ {
@ -613,7 +631,7 @@ const Mihomo: React.FC = () => {
<SettingCard> <SettingCard>
<SettingItem title={t('mihomo.mixedPort')} divider> <SettingItem title={t('mihomo.mixedPort')} divider>
<div className="flex"> <div className="flex">
{mixedPortInput !== mixedPort && ( {isManualPortChange && mixedPortInput !== mixedPort && (
<Button <Button
size="sm" size="sm"
color="primary" color="primary"
@ -634,24 +652,53 @@ const Mihomo: React.FC = () => {
size="sm" size="sm"
type="number" type="number"
className="w-[100px]" className="w-[100px]"
value={mixedPortInput.toString()} value={showMixedPort?.toString()}
max={65535} max={65535}
min={0} min={0}
onValueChange={(v) => { onValueChange={(v) => {
setMixedPortInput(parseInt(v)) patchAppConfig({ showMixedPort: parseInt(v) })
setIsManualPortChange(true)
}}
/>
<Button
isIconOnly
size="sm"
variant="light"
className="ml-2"
onPress={() => {
const randomPort = generateRandomPort()
setMixedPortInput(randomPort)
patchAppConfig({ showMixedPort: randomPort })
setIsManualPortChange(true)
}}
>
<IoMdShuffle className="text-lg" />
</Button>
<Switch
size="sm"
className="ml-2"
isSelected={enableMixedPort}
onValueChange={(value) => {
patchAppConfig({ enableMixedPort: value })
if (value) {
const port = appConfig?.showMixedPort
onChangeNeedRestart({ 'mixed-port': port })
} else {
onChangeNeedRestart({ 'mixed-port': 0 })
}
}} }}
/> />
</div> </div>
</SettingItem> </SettingItem>
<SettingItem title={t('mihomo.socksPort')} divider> <SettingItem title={t('mihomo.socksPort')} divider>
<div className="flex"> <div className="flex">
{socksPortInput !== socksPort && ( {isManualPortChange && socksPortInput !== socksPort && (
<Button <Button
size="sm" size="sm"
color="primary" color="primary"
className="mr-2" className="mr-2"
onPress={() => { onPress={async () => {
onChangeNeedRestart({ 'socks-port': socksPortInput }) await onChangeNeedRestart({ 'socks-port': socksPortInput })
}} }}
> >
{t('mihomo.confirm')} {t('mihomo.confirm')}
@ -662,24 +709,55 @@ const Mihomo: React.FC = () => {
size="sm" size="sm"
type="number" type="number"
className="w-[100px]" className="w-[100px]"
value={socksPortInput.toString()} value={showSocksPort?.toString()}
max={65535} max={65535}
min={0} min={0}
onValueChange={(v) => { onValueChange={(v) => {
setSocksPortInput(parseInt(v)) const port = parseInt(v)
setSocksPortInput(port)
patchAppConfig({ showSocksPort: port })
setIsManualPortChange(true)
}}
/>
<Button
isIconOnly
size="sm"
variant="light"
className="ml-2"
onPress={() => {
const randomPort = generateRandomPort()
setSocksPortInput(randomPort)
patchAppConfig({ showSocksPort: randomPort })
setIsManualPortChange(true)
}}
>
<IoMdShuffle className="text-lg" />
</Button>
<Switch
size="sm"
className="ml-2"
isSelected={enableSocksPort}
onValueChange={(value) => {
patchAppConfig({ enableSocksPort: value })
if (value) {
const port = appConfig?.showSocksPort || socksPort
onChangeNeedRestart({ 'socks-port': port })
} else {
onChangeNeedRestart({ 'socks-port': 0 })
}
}} }}
/> />
</div> </div>
</SettingItem> </SettingItem>
<SettingItem title={t('mihomo.httpPort')} divider> <SettingItem title={t('mihomo.httpPort')} divider>
<div className="flex"> <div className="flex">
{httpPortInput !== httpPort && ( {isManualPortChange && httpPortInput !== httpPort && (
<Button <Button
size="sm" size="sm"
color="primary" color="primary"
className="mr-2" className="mr-2"
onPress={() => { onPress={async () => {
onChangeNeedRestart({ port: httpPortInput }) await onChangeNeedRestart({ port: httpPortInput })
}} }}
> >
{t('mihomo.confirm')} {t('mihomo.confirm')}
@ -690,11 +768,42 @@ const Mihomo: React.FC = () => {
size="sm" size="sm"
type="number" type="number"
className="w-[100px]" className="w-[100px]"
value={httpPortInput.toString()} value={showHttpPort?.toString()}
max={65535} max={65535}
min={0} min={0}
onValueChange={(v) => { onValueChange={(v) => {
setHttpPortInput(parseInt(v)) const port = parseInt(v)
setHttpPortInput(port)
patchAppConfig({ showHttpPort: port })
setIsManualPortChange(true)
}}
/>
<Button
isIconOnly
size="sm"
variant="light"
className="ml-2"
onPress={() => {
const randomPort = generateRandomPort()
setHttpPortInput(randomPort)
patchAppConfig({ showHttpPort: randomPort })
setIsManualPortChange(true)
}}
>
<IoMdShuffle className="text-lg" />
</Button>
<Switch
size="sm"
className="ml-2"
isSelected={enableHttpPort}
onValueChange={(value) => {
patchAppConfig({ enableHttpPort: value })
if (value) {
const port = appConfig?.showHttpPort || httpPort
onChangeNeedRestart({ port: port })
} else {
onChangeNeedRestart({ port: 0 })
}
}} }}
/> />
</div> </div>
@ -702,13 +811,13 @@ const Mihomo: React.FC = () => {
{platform !== 'win32' && ( {platform !== 'win32' && (
<SettingItem title={t('mihomo.redirPort')} divider> <SettingItem title={t('mihomo.redirPort')} divider>
<div className="flex"> <div className="flex">
{redirPortInput !== redirPort && ( {isManualPortChange && redirPortInput !== redirPort && (
<Button <Button
size="sm" size="sm"
color="primary" color="primary"
className="mr-2" className="mr-2"
onPress={() => { onPress={async () => {
onChangeNeedRestart({ 'redir-port': redirPortInput }) await onChangeNeedRestart({ 'redir-port': redirPortInput })
}} }}
> >
{t('mihomo.confirm')} {t('mihomo.confirm')}
@ -719,11 +828,42 @@ const Mihomo: React.FC = () => {
size="sm" size="sm"
type="number" type="number"
className="w-[100px]" className="w-[100px]"
value={redirPortInput.toString()} value={showRedirPort?.toString()}
max={65535} max={65535}
min={0} min={0}
onValueChange={(v) => { onValueChange={(v) => {
setRedirPortInput(parseInt(v)) const port = parseInt(v)
setRedirPortInput(port)
patchAppConfig({ showRedirPort: port })
setIsManualPortChange(true)
}}
/>
<Button
isIconOnly
size="sm"
variant="light"
className="ml-2"
onPress={() => {
const randomPort = generateRandomPort()
setRedirPortInput(randomPort)
patchAppConfig({ showRedirPort: randomPort })
setIsManualPortChange(true)
}}
>
<IoMdShuffle className="text-lg" />
</Button>
<Switch
size="sm"
className="ml-2"
isSelected={enableRedirPort}
onValueChange={(value) => {
patchAppConfig({ enableRedirPort: value })
if (value) {
const port = appConfig?.showRedirPort || redirPort
onChangeNeedRestart({ 'redir-port': port })
} else {
onChangeNeedRestart({ 'redir-port': 0 })
}
}} }}
/> />
</div> </div>
@ -732,13 +872,13 @@ const Mihomo: React.FC = () => {
{platform === 'linux' && ( {platform === 'linux' && (
<SettingItem title={t('mihomo.tproxyPort')} divider> <SettingItem title={t('mihomo.tproxyPort')} divider>
<div className="flex"> <div className="flex">
{tproxyPortInput !== tproxyPort && ( {isManualPortChange && tproxyPortInput !== tproxyPort && (
<Button <Button
size="sm" size="sm"
color="primary" color="primary"
className="mr-2" className="mr-2"
onPress={() => { onPress={async () => {
onChangeNeedRestart({ 'tproxy-port': tproxyPortInput }) await onChangeNeedRestart({ 'tproxy-port': tproxyPortInput })
}} }}
> >
{t('mihomo.confirm')} {t('mihomo.confirm')}
@ -749,11 +889,42 @@ const Mihomo: React.FC = () => {
size="sm" size="sm"
type="number" type="number"
className="w-[100px]" className="w-[100px]"
value={tproxyPortInput.toString()} value={showTproxyPort?.toString()}
max={65535} max={65535}
min={0} min={0}
onValueChange={(v) => { onValueChange={(v) => {
setTproxyPortInput(parseInt(v)) const port = parseInt(v)
setTproxyPortInput(port)
patchAppConfig({ showTproxyPort: port })
setIsManualPortChange(true)
}}
/>
<Button
isIconOnly
size="sm"
variant="light"
className="ml-2"
onPress={() => {
const randomPort = generateRandomPort()
setTproxyPortInput(randomPort)
patchAppConfig({ showTproxyPort: randomPort })
setIsManualPortChange(true)
}}
>
<IoMdShuffle className="text-lg" />
</Button>
<Switch
size="sm"
className="ml-2"
isSelected={enableTproxyPort}
onValueChange={(value) => {
patchAppConfig({ enableTproxyPort: value })
if (value) {
const port = appConfig?.showTproxyPort || tproxyPort
onChangeNeedRestart({ 'tproxy-port': port })
} else {
onChangeNeedRestart({ 'tproxy-port': 0 })
}
}} }}
/> />
</div> </div>

10
src/shared/types.d.ts vendored
View File

@ -312,6 +312,16 @@ interface IAppConfig {
quitWithoutCoreShortcut?: string quitWithoutCoreShortcut?: string
language?: 'zh-CN' | 'en-US' | 'ru-RU' | 'fa-IR' language?: 'zh-CN' | 'en-US' | 'ru-RU' | 'fa-IR'
triggerMainWindowBehavior?: 'show' | 'toggle' triggerMainWindowBehavior?: 'show' | 'toggle'
showMixedPort?: number
enableMixedPort?: boolean
showSocksPort?: number
enableSocksPort?: boolean
showHttpPort?: number
enableHttpPort?: boolean
showRedirPort?: number
enableRedirPort?: boolean
showTproxyPort?: number
enableTproxyPort?: boolean
} }
interface IMihomoTunConfig { interface IMihomoTunConfig {