mirror of
https://github.com/yaklang/yaklang-chrome-extension.git
synced 2026-09-22 03:10:43 +08:00
fix pac script
This commit is contained in:
@@ -214,21 +214,33 @@ export const ProxySwitch: React.FC = () => {
|
||||
// 添加自定义代理
|
||||
if (customProxies.length > 0) {
|
||||
items.push(
|
||||
...customProxies.map(proxy => ({
|
||||
key: proxy.key,
|
||||
label: proxy.name,
|
||||
icon: <img
|
||||
src={YAK_ICON_URL}
|
||||
alt="YAK"
|
||||
style={{
|
||||
width: 20,
|
||||
height: 20,
|
||||
filter: currentMode === proxy.key ? 'brightness(0) invert(1)' : 'none',
|
||||
transition: 'filter 0.2s ease-in-out'
|
||||
}}
|
||||
/>,
|
||||
className: `${currentMode === proxy.key ? 'active-item' : ''} menu-id-${proxy.key}`,
|
||||
}))
|
||||
...customProxies.map(proxy => {
|
||||
// 构建提示信息:显示代理协议、主机和端口
|
||||
const tooltipText = proxy.config.proxyType === 'fixed_servers' && proxy.config.host && proxy.config.port
|
||||
? `${proxy.config.scheme || 'http'}://${proxy.config.host}:${proxy.config.port}`
|
||||
: proxy.config.proxyType === 'pac_script'
|
||||
? 'PAC脚本代理'
|
||||
: proxy.config.proxyType === 'auto_detect'
|
||||
? '自动检测代理'
|
||||
: '';
|
||||
|
||||
return {
|
||||
key: proxy.key,
|
||||
label: proxy.name,
|
||||
icon: <img
|
||||
src={YAK_ICON_URL}
|
||||
alt="YAK"
|
||||
style={{
|
||||
width: 20,
|
||||
height: 20,
|
||||
filter: currentMode === proxy.key ? 'brightness(0) invert(1)' : 'none',
|
||||
transition: 'filter 0.2s ease-in-out'
|
||||
}}
|
||||
/>,
|
||||
className: `${currentMode === proxy.key ? 'active-item' : ''} menu-id-${proxy.key}`,
|
||||
title: tooltipText, // 添加悬停提示
|
||||
};
|
||||
})
|
||||
);
|
||||
items.push({type: 'divider'});
|
||||
}
|
||||
|
||||
+188
-99
@@ -1,12 +1,31 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { ConfigProvider, Layout, Typography, List, Button, Form, Input, Select, Space, Card, Divider, Modal } from 'antd';
|
||||
import { PlusOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { browser } from 'wxt/browser';
|
||||
import type { ProxyConfig } from '../../types/proxy';
|
||||
import { getAllProxyConfigs, saveProxyConfig, deleteProxyConfig, enableProxyConfig, getCurrentProxy } from '../../utils/storage';
|
||||
import {ContentActionType, ProxyActionType} from '../../types/action';
|
||||
import './App.css';
|
||||
import React, { useState, useEffect } from "react";
|
||||
import {
|
||||
ConfigProvider,
|
||||
Layout,
|
||||
Typography,
|
||||
List,
|
||||
Button,
|
||||
Form,
|
||||
Input,
|
||||
Select,
|
||||
Space,
|
||||
Card,
|
||||
Divider,
|
||||
Modal,
|
||||
} from "antd";
|
||||
import { PlusOutlined, DeleteOutlined } from "@ant-design/icons";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { browser } from "wxt/browser";
|
||||
import type { ProxyConfig } from "../../types/proxy";
|
||||
import {
|
||||
getAllProxyConfigs,
|
||||
saveProxyConfig,
|
||||
deleteProxyConfig,
|
||||
enableProxyConfig,
|
||||
getCurrentProxy,
|
||||
} from "../../utils/storage";
|
||||
import { ContentActionType, ProxyActionType } from "../../types/action";
|
||||
import "./App.css";
|
||||
|
||||
const { Header, Content } = Layout;
|
||||
const { Title } = Typography;
|
||||
@@ -44,27 +63,34 @@ export default function App() {
|
||||
|
||||
// 获取当前启用的代理
|
||||
const currentProxy = await getCurrentProxy();
|
||||
const currentProxyId = currentProxy?.id || '';
|
||||
const currentProxyId = currentProxy?.id || "";
|
||||
|
||||
// 检查当前是否为系统代理或直接连接
|
||||
const isSystemOrDirect = currentProxyId === 'system' || currentProxyId === 'direct';
|
||||
const isSystemOrDirect =
|
||||
currentProxyId === "system" || currentProxyId === "direct";
|
||||
|
||||
// 只显示自定义代理服务器配置
|
||||
const customProxies = allConfigs.filter(config => config.proxyType === "fixed_servers");
|
||||
// 显示自定义代理服务器配置和PAC脚本配置
|
||||
const customProxies = allConfigs.filter(
|
||||
(config) =>
|
||||
config.proxyType === "fixed_servers" ||
|
||||
config.proxyType === "pac_script"
|
||||
);
|
||||
|
||||
// 如果当前是系统代理或直接连接,则所有自定义代理显示为未启用
|
||||
if (isSystemOrDirect) {
|
||||
console.log('系统代理或直接连接已启用,确保自定义代理状态正确');
|
||||
console.log("系统代理或直接连接已启用,确保自定义代理状态正确");
|
||||
// 确保UI状态与实际状态一致
|
||||
setProxies(customProxies.map(proxy => ({
|
||||
...proxy,
|
||||
enabled: false
|
||||
})));
|
||||
setProxies(
|
||||
customProxies.map((proxy) => ({
|
||||
...proxy,
|
||||
enabled: false,
|
||||
}))
|
||||
);
|
||||
} else {
|
||||
setProxies(customProxies);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading proxies:', error);
|
||||
console.error("Error loading proxies:", error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -75,11 +101,11 @@ export default function App() {
|
||||
const newProxy: Partial<ProxyConfig> = {
|
||||
id: uuidv4(),
|
||||
name: values.name,
|
||||
enabled: false
|
||||
enabled: false,
|
||||
};
|
||||
|
||||
if (values.proxyType === 'fixed_servers') {
|
||||
newProxy.proxyType = 'fixed_servers';
|
||||
if (values.proxyType === "fixed_servers") {
|
||||
newProxy.proxyType = "fixed_servers";
|
||||
newProxy.scheme = values.scheme;
|
||||
newProxy.host = values.host;
|
||||
newProxy.port = Number(values.port);
|
||||
@@ -87,46 +113,58 @@ export default function App() {
|
||||
// 处理不经过代理的地址
|
||||
if (values.bypassList) {
|
||||
newProxy.bypassList = values.bypassList
|
||||
.split('\n')
|
||||
.split("\n")
|
||||
.map((line: string) => line.trim())
|
||||
.filter((line: string) => line.length > 0);
|
||||
} else {
|
||||
newProxy.bypassList = [];
|
||||
}
|
||||
} else if (values.proxyType === 'pac_script') {
|
||||
newProxy.proxyType = 'pac_script';
|
||||
newProxy.mode = 'pac_script';
|
||||
} else if (values.proxyType === "pac_script") {
|
||||
newProxy.proxyType = "pac_script";
|
||||
newProxy.mode = "pac_script";
|
||||
|
||||
// 处理PAC脚本匹配域名
|
||||
if (values.matchList) {
|
||||
newProxy.matchList = values.matchList
|
||||
.split('\n')
|
||||
.split("\n")
|
||||
.map((line: string) => line.trim())
|
||||
.filter((line: string) => line.length > 0);
|
||||
}
|
||||
|
||||
// 解析选择的代理服务器
|
||||
const [host, port] = values.proxyServer.split(":");
|
||||
|
||||
// 创建PAC脚本
|
||||
newProxy.pacScript = {
|
||||
data: `function FindProxyForURL(url, host) {
|
||||
// 匹配域名列表
|
||||
const domains = ${JSON.stringify(newProxy.matchList || [])};
|
||||
// Convert host to lowercase for case-insensitive matching
|
||||
host = host.toLowerCase();
|
||||
|
||||
// 检查是否匹配任何域名
|
||||
for (let i = 0; i < domains.length; i++) {
|
||||
const domain = domains[i];
|
||||
// 支持通配符
|
||||
if (domain.startsWith('*.') && host.endsWith(domain.substring(1))) {
|
||||
return 'PROXY ${values.host}:${values.port}';
|
||||
} else if (host === domain) {
|
||||
return 'PROXY ${values.host}:${values.port}';
|
||||
// Define domain patterns
|
||||
var domains = ${JSON.stringify(newProxy.matchList || [])};
|
||||
|
||||
// Check each domain pattern
|
||||
for (var i = 0; i < domains.length; i++) {
|
||||
var pattern = domains[i].toLowerCase();
|
||||
|
||||
if (pattern.startsWith('*.')) {
|
||||
var suffix = pattern.substring(2);
|
||||
if (host === suffix || host.endsWith('.' + suffix)) {
|
||||
return 'PROXY ${host}:${port}';
|
||||
}
|
||||
} else if (host === pattern) {
|
||||
return 'PROXY ${host}:${port}';
|
||||
}
|
||||
}
|
||||
|
||||
// 默认直接连接
|
||||
return 'DIRECT';
|
||||
}`,
|
||||
mandatory: true
|
||||
mandatory: true,
|
||||
};
|
||||
|
||||
// 保存代理服务器信息
|
||||
newProxy.host = host;
|
||||
newProxy.port = Number(port);
|
||||
}
|
||||
|
||||
// 添加认证信息
|
||||
@@ -147,10 +185,10 @@ export default function App() {
|
||||
// 通知后台脚本
|
||||
browser.runtime.sendMessage({
|
||||
action: ContentActionType.PROXY_CONFIGS_UPDATED,
|
||||
source: 'options'
|
||||
source: "options",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error saving proxy:', error);
|
||||
console.error("Error saving proxy:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -164,7 +202,7 @@ export default function App() {
|
||||
// 通知后台脚本
|
||||
browser.runtime.sendMessage({
|
||||
action: ContentActionType.PROXY_CONFIGS_UPDATED,
|
||||
source: 'options'
|
||||
source: "options",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`Error deleting proxy ${id}:`, error);
|
||||
@@ -179,7 +217,7 @@ export default function App() {
|
||||
// 发送切换代理请求
|
||||
await browser.runtime.sendMessage({
|
||||
action: ProxyActionType.SWITCH_PROXY,
|
||||
mode: id
|
||||
mode: id,
|
||||
});
|
||||
|
||||
// 重新加载代理列表
|
||||
@@ -188,7 +226,7 @@ export default function App() {
|
||||
// 通知后台脚本
|
||||
browser.runtime.sendMessage({
|
||||
action: ContentActionType.PROXY_CONFIGS_UPDATED,
|
||||
source: 'options'
|
||||
source: "options",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`Error activating proxy ${id}:`, error);
|
||||
@@ -214,7 +252,9 @@ export default function App() {
|
||||
>
|
||||
<Layout className="options-layout">
|
||||
<Header className="options-header">
|
||||
<Title level={3} style={{ color: 'white', margin: 0 }}>Yaklang 代理管理设置</Title>
|
||||
<Title level={3} style={{ color: "white", margin: 0 }}>
|
||||
Yaklang 代理管理设置
|
||||
</Title>
|
||||
</Header>
|
||||
<Content className="options-content">
|
||||
<Card
|
||||
@@ -230,7 +270,7 @@ export default function App() {
|
||||
backgroundColor: "#F28B44",
|
||||
borderColor: "#F28B44",
|
||||
borderRadius: "4px",
|
||||
fontSize: "13px"
|
||||
fontSize: "13px",
|
||||
}}
|
||||
>
|
||||
添加代理
|
||||
@@ -241,7 +281,7 @@ export default function App() {
|
||||
dataSource={proxies}
|
||||
locale={{
|
||||
emptyText: (
|
||||
<div style={{ padding: '32px 0', textAlign: 'center' }}>
|
||||
<div style={{ padding: "32px 0", textAlign: "center" }}>
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTUzLjMzMzMgMzJWNDhDNTMuMzMzMyA0OS40MTc0IDUyLjc3MTQgNTAuNzY1MiA1MS43NzEyIDUxLjc2NTJDNTAuNzcxIDUyLjc2NTIgNDkuNDIzMyA1My4zMzMzIDQ4IDUzLjMzMzNIMTZDMTQuNTc2NyA1My4zMzMzIDEzLjIyODkgNTIuNzcxNCAxMi4yMjg4IDUxLjc3MTJDMTEuMjI4OCA1MC43NzEgMTAuNjY2NyA0OS40MjMzIDEwLjY2NjcgNDhWMTZDMTAuNjY2NyAxNC41NzY3IDExLjIyODggMTMuMjI4OSAxMi4yMjg4IDEyLjIyODhDMTMuMjI4OSAxMS4yMjg4IDE0LjU3NjcgMTAuNjY2NyAxNiAxMC42NjY3SDMyIiBzdHJva2U9IiM1QTVBNUEiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxwYXRoIGQ9Ik0zMiAzMkg1My4zMzMzVjQyLjY2NjciIHN0cm9rZT0iI0YyOEI0NCIgc3Ryb2tlLXdpZHRoPSI0IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+Cg=="
|
||||
@@ -249,9 +289,9 @@ export default function App() {
|
||||
style={{ width: 64, height: 64, opacity: 0.5 }}
|
||||
/>
|
||||
</div>
|
||||
<p style={{ color: '#5A5A5A' }}>还没有添加任何代理</p>
|
||||
<p style={{ color: "#5A5A5A" }}>还没有添加任何代理</p>
|
||||
</div>
|
||||
)
|
||||
),
|
||||
}}
|
||||
renderItem={(proxy) => (
|
||||
<List.Item
|
||||
@@ -261,24 +301,32 @@ export default function App() {
|
||||
type={proxy.enabled ? "default" : "primary"}
|
||||
onClick={() => handleActivate(proxy.id)}
|
||||
disabled={proxy.enabled}
|
||||
style={proxy.enabled ? {
|
||||
backgroundColor: "#F28B44",
|
||||
color: "white",
|
||||
borderColor: "#F28B44"
|
||||
} : undefined}
|
||||
style={
|
||||
proxy.enabled
|
||||
? {
|
||||
backgroundColor: "#F28B44",
|
||||
color: "white",
|
||||
borderColor: "#F28B44",
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{proxy.enabled ? '已启用' : '启用'}
|
||||
{proxy.enabled ? "已启用" : "启用"}
|
||||
</Button>,
|
||||
<Button
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={() => handleDelete(proxy.id)}
|
||||
/>
|
||||
/>,
|
||||
]}
|
||||
>
|
||||
<List.Item.Meta
|
||||
title={proxy.name}
|
||||
description={`${proxy.scheme}://${proxy.host}:${proxy.port}`}
|
||||
description={
|
||||
proxy.proxyType === "pac_script"
|
||||
? `PAC 脚本 (使用 ${proxy.host}:${proxy.port} 作为代理)`
|
||||
: `${proxy.scheme}://${proxy.host}:${proxy.port}`
|
||||
}
|
||||
/>
|
||||
</List.Item>
|
||||
)}
|
||||
@@ -289,7 +337,7 @@ export default function App() {
|
||||
<Modal
|
||||
title="添加新代理"
|
||||
open={isModalOpen}
|
||||
className='add-proxy-card'
|
||||
className="add-proxy-card"
|
||||
onCancel={handleCancel}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={handleCancel}>
|
||||
@@ -302,19 +350,15 @@ export default function App() {
|
||||
loading={loading}
|
||||
>
|
||||
OK
|
||||
</Button>
|
||||
</Button>,
|
||||
]}
|
||||
destroyOnClose
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
onFinish={handleSave}
|
||||
>
|
||||
<Form form={form} layout="vertical" onFinish={handleSave}>
|
||||
<Form.Item
|
||||
name="name"
|
||||
label={<span className="required-label">名称</span>}
|
||||
rules={[{ required: true, message: '请输入代理名称' }]}
|
||||
rules={[{ required: true, message: "请输入代理名称" }]}
|
||||
>
|
||||
<Input placeholder="为此代理添加一个名称" />
|
||||
</Form.Item>
|
||||
@@ -323,7 +367,7 @@ export default function App() {
|
||||
name="proxyType"
|
||||
label={<span className="required-label">类型</span>}
|
||||
initialValue="fixed_servers"
|
||||
rules={[{ required: true, message: '请选择代理类型' }]}
|
||||
rules={[{ required: true, message: "请选择代理类型" }]}
|
||||
>
|
||||
<Select>
|
||||
<Option value="fixed_servers">代理服务器</Option>
|
||||
@@ -333,18 +377,22 @@ export default function App() {
|
||||
|
||||
<Form.Item
|
||||
noStyle
|
||||
shouldUpdate={(prevValues, currentValues) => prevValues.proxyType !== currentValues.proxyType}
|
||||
shouldUpdate={(prevValues, currentValues) =>
|
||||
prevValues.proxyType !== currentValues.proxyType
|
||||
}
|
||||
>
|
||||
{({ getFieldValue }) => {
|
||||
const proxyType = getFieldValue('proxyType');
|
||||
if (proxyType === 'fixed_servers') {
|
||||
const proxyType = getFieldValue("proxyType");
|
||||
if (proxyType === "fixed_servers") {
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="scheme"
|
||||
label={<span className="required-label">协议</span>}
|
||||
initialValue="http"
|
||||
rules={[{ required: true, message: '请选择代理协议' }]}
|
||||
rules={[
|
||||
{ required: true, message: "请选择代理协议" },
|
||||
]}
|
||||
>
|
||||
<Select>
|
||||
<Option value="http">HTTP</Option>
|
||||
@@ -357,7 +405,9 @@ export default function App() {
|
||||
<Form.Item
|
||||
name="host"
|
||||
label={<span className="required-label">主机</span>}
|
||||
rules={[{ required: true, message: '请输入主机地址' }]}
|
||||
rules={[
|
||||
{ required: true, message: "请输入主机地址" },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="127.0.0.1" />
|
||||
</Form.Item>
|
||||
@@ -365,15 +415,12 @@ export default function App() {
|
||||
<Form.Item
|
||||
name="port"
|
||||
label={<span className="required-label">端口</span>}
|
||||
rules={[{ required: true, message: '请输入端口' }]}
|
||||
rules={[{ required: true, message: "请输入端口" }]}
|
||||
>
|
||||
<Input placeholder="8080" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="bypassList"
|
||||
label="不经过代理的地址"
|
||||
>
|
||||
<Form.Item name="bypassList" label="不经过代理的地址">
|
||||
<Input.TextArea
|
||||
rows={4}
|
||||
placeholder={`例如:
|
||||
@@ -381,17 +428,49 @@ localhost
|
||||
127.0.0.1
|
||||
*.example.com`}
|
||||
/>
|
||||
<div style={{ marginTop: 8, fontSize: 12, color: '#999' }}>每行一个地址,支持通配符 *</div>
|
||||
<div
|
||||
style={{
|
||||
marginTop: 8,
|
||||
fontSize: 12,
|
||||
color: "#999",
|
||||
}}
|
||||
>
|
||||
每行一个地址,支持通配符 *
|
||||
</div>
|
||||
</Form.Item>
|
||||
|
||||
<Space style={{ display: "flex" }}>
|
||||
<Form.Item
|
||||
name="username"
|
||||
label="用户名 (可选)"
|
||||
style={{ flex: 1 }}
|
||||
>
|
||||
<Input placeholder="认证用户名" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="password"
|
||||
label="密码 (可选)"
|
||||
style={{ flex: 1 }}
|
||||
>
|
||||
<Input.Password placeholder="认证密码" />
|
||||
</Form.Item>
|
||||
</Space>
|
||||
</>
|
||||
);
|
||||
} else if (proxyType === 'pac_script') {
|
||||
} else if (proxyType === "pac_script") {
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="matchList"
|
||||
label={<span className="required-label">匹配域名</span>}
|
||||
rules={[{ required: true, message: '请输入至少一个匹配域名' }]}
|
||||
label="匹配域名"
|
||||
help="每行一个域名,支持通配符 *"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "请输入至少一个匹配域名",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input.TextArea
|
||||
rows={4}
|
||||
@@ -400,7 +479,35 @@ localhost
|
||||
google.com
|
||||
github.com`}
|
||||
/>
|
||||
<div style={{ marginTop: 8, fontSize: 12, color: '#999' }}>每行一个域名,支持通配符 *</div>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="proxyServer"
|
||||
label={
|
||||
<span className="required-label">
|
||||
选择代理服务器
|
||||
</span>
|
||||
}
|
||||
rules={[
|
||||
{ required: true, message: "请选择代理服务器" },
|
||||
]}
|
||||
>
|
||||
<Select placeholder="选择一个代理服务器">
|
||||
{/* 获取已配置的固定代理服务器列表 */}
|
||||
{proxies
|
||||
.filter(
|
||||
(proxy) => proxy.proxyType === "fixed_servers"
|
||||
)
|
||||
.map((proxy) => (
|
||||
<Option
|
||||
key={proxy.id}
|
||||
value={`${proxy.host}:${proxy.port}`}
|
||||
>
|
||||
{proxy.name} ({proxy.scheme}://{proxy.host}:
|
||||
{proxy.port})
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
@@ -408,24 +515,6 @@ github.com`}
|
||||
return null;
|
||||
}}
|
||||
</Form.Item>
|
||||
|
||||
<Space style={{ display: 'flex' }}>
|
||||
<Form.Item
|
||||
name="username"
|
||||
label="用户名 (可选)"
|
||||
style={{ flex: 1 }}
|
||||
>
|
||||
<Input placeholder="认证用户名" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="password"
|
||||
label="密码 (可选)"
|
||||
style={{ flex: 1 }}
|
||||
>
|
||||
<Input.Password placeholder="认证密码" />
|
||||
</Form.Item>
|
||||
</Space>
|
||||
</Form>
|
||||
</Modal>
|
||||
</Content>
|
||||
|
||||
Reference in New Issue
Block a user