feat(network): integrate outbound route module on Ultra1.4 baseline
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,35 @@
|
||||
// sidepanel/ip-proxy-provider-711proxy.js — 711Proxy 面板专属逻辑
|
||||
function normalizeIpProxyCountryCode(value = '') {
|
||||
const raw = String(value || '').trim().toUpperCase().replace(/[^A-Z]/g, '');
|
||||
return /^[A-Z]{2}$/.test(raw) ? raw : '';
|
||||
}
|
||||
|
||||
function infer711RegionFromHost(host = '') {
|
||||
const text = String(host || '').trim().toLowerCase().replace(/\.$/, '');
|
||||
if (!text || !text.includes('.')) {
|
||||
return '';
|
||||
}
|
||||
const firstLabel = String(text.split('.')[0] || '').trim();
|
||||
return /^[a-z]{2}$/.test(firstLabel) ? firstLabel.toUpperCase() : '';
|
||||
}
|
||||
|
||||
function infer711RegionFromUsername(username = '') {
|
||||
const text = String(username || '').trim();
|
||||
if (!text) {
|
||||
return '';
|
||||
}
|
||||
const match = text.match(/(?:^|[-_])region[-_:]?([A-Za-z]{2})\b/i);
|
||||
return normalizeIpProxyCountryCode(match ? match[1] : '');
|
||||
}
|
||||
|
||||
function resolve711ProxyRegionFromInputs({ host = '', username = '', region = '' } = {}) {
|
||||
const fromUsername = infer711RegionFromUsername(username);
|
||||
if (fromUsername) {
|
||||
return fromUsername;
|
||||
}
|
||||
const fromHost = infer711RegionFromHost(host);
|
||||
if (fromHost) {
|
||||
return fromHost;
|
||||
}
|
||||
return normalizeIpProxyCountryCode(region);
|
||||
}
|
||||
@@ -781,6 +781,248 @@ header {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.ip-proxy-fold-row {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ip-proxy-fold {
|
||||
width: 100%;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ip-proxy-fold-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
border-top: none;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.ip-proxy-layout-row {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ip-proxy-layout {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ip-proxy-layout.is-account-only {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ip-proxy-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.ip-proxy-column-header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ip-proxy-column-hint {
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.ip-proxy-column-mode-btn {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ip-proxy-column-api.is-disabled {
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
.ip-proxy-column-api.is-disabled .data-input,
|
||||
.ip-proxy-column-api.is-disabled .data-select,
|
||||
.ip-proxy-column-api.is-disabled .data-textarea,
|
||||
.ip-proxy-column-api.is-disabled .input-icon-btn,
|
||||
.ip-proxy-column-api.is-disabled .btn,
|
||||
.ip-proxy-column-api.is-disabled .choice-btn {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.ip-proxy-layout {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.ip-proxy-enabled-inline {
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.ip-proxy-actions-inline {
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
row-gap: 6px;
|
||||
}
|
||||
|
||||
.ip-proxy-action-grid {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.ip-proxy-action-grid .data-inline-btn {
|
||||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.ip-proxy-action-hint {
|
||||
flex: 1 1 100%;
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.ip-proxy-enabled-status {
|
||||
margin-left: auto;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 6px;
|
||||
min-width: 92px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ip-proxy-enabled-status-dot {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 999px;
|
||||
background: var(--text-muted);
|
||||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--text-muted) 25%, transparent);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ip-proxy-enabled-status.is-on {
|
||||
color: var(--green);
|
||||
}
|
||||
|
||||
.ip-proxy-enabled-status.is-on .ip-proxy-enabled-status-dot {
|
||||
background: var(--green);
|
||||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--green) 30%, transparent);
|
||||
}
|
||||
|
||||
.ip-proxy-enabled-status.is-off {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.ip-proxy-runtime-status {
|
||||
display: inline-flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
min-height: 32px;
|
||||
padding: 6px 10px;
|
||||
border: 1px solid var(--border-subtle);
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--bg-surface);
|
||||
}
|
||||
|
||||
.ip-proxy-runtime-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.ip-proxy-runtime-main {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.ip-proxy-runtime-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.ip-proxy-check-ip-btn {
|
||||
min-width: 64px;
|
||||
padding-inline: 10px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ip-proxy-runtime-current {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.ip-proxy-runtime-current.has-value {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.ip-proxy-runtime-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 999px;
|
||||
background: var(--text-muted);
|
||||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--text-muted) 28%, transparent);
|
||||
flex-shrink: 0;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.ip-proxy-runtime-status.state-applied .ip-proxy-runtime-dot {
|
||||
background: var(--green);
|
||||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--green) 28%, transparent);
|
||||
}
|
||||
|
||||
.ip-proxy-runtime-status.state-warning .ip-proxy-runtime-dot {
|
||||
background: var(--orange);
|
||||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--orange) 28%, transparent);
|
||||
}
|
||||
|
||||
.ip-proxy-runtime-status.state-error .ip-proxy-runtime-dot {
|
||||
background: var(--red);
|
||||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--red) 28%, transparent);
|
||||
}
|
||||
|
||||
.ip-proxy-runtime-details {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ip-proxy-runtime-details summary {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
color: var(--text-secondary);
|
||||
font-size: 11px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.ip-proxy-runtime-details[open] summary {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.ip-proxy-runtime-details-text {
|
||||
margin-top: 4px;
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
color: var(--text-secondary);
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.mail2925-base-inline {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
@@ -194,6 +194,163 @@
|
||||
<span class="data-label">默认代理</span>
|
||||
<input type="text" id="input-sub2api-default-proxy" class="data-input" placeholder="留空则不使用代理;或填写代理名称 / ID" />
|
||||
</div>
|
||||
<div class="data-row" id="row-ip-proxy-enabled">
|
||||
<span class="data-label">IP代理</span>
|
||||
<div class="data-inline ip-proxy-enabled-inline">
|
||||
<label class="toggle-switch" for="input-ip-proxy-enabled" title="启用或禁用 IP 代理接管">
|
||||
<input type="checkbox" id="input-ip-proxy-enabled" />
|
||||
<span class="toggle-switch-track" aria-hidden="true">
|
||||
<span class="toggle-switch-thumb"></span>
|
||||
</span>
|
||||
</label>
|
||||
<span id="ip-proxy-enabled-status" class="ip-proxy-enabled-status" aria-live="polite">
|
||||
<span id="ip-proxy-enabled-status-dot" class="ip-proxy-enabled-status-dot" aria-hidden="true"></span>
|
||||
<span id="ip-proxy-enabled-status-text" class="ip-proxy-enabled-status-text">未开启</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-row ip-proxy-fold-row" id="row-ip-proxy-fold" style="display:none;">
|
||||
<div id="ip-proxy-fold" class="ip-proxy-fold">
|
||||
<div class="ip-proxy-fold-body">
|
||||
<div class="data-row" id="row-ip-proxy-service" style="display:none;">
|
||||
<span class="data-label">代理服务</span>
|
||||
<div class="data-inline">
|
||||
<select id="select-ip-proxy-service" class="data-select" disabled>
|
||||
<option value="711proxy">711Proxy(首版)</option>
|
||||
</select>
|
||||
<button id="btn-ip-proxy-service-login" class="btn btn-outline btn-sm data-inline-btn" type="button">
|
||||
登录
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-row" id="row-ip-proxy-mode" style="display:none;">
|
||||
<span class="data-label">代理模式</span>
|
||||
<div id="ip-proxy-mode-group" class="choice-group" role="group" aria-label="IP代理模式">
|
||||
<button type="button" class="choice-btn" data-ip-proxy-mode="account">账号密码</button>
|
||||
<button type="button" class="choice-btn" data-ip-proxy-mode="api" disabled title="首版暂未开放">API 拉取(暂未开放)</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-row ip-proxy-layout-row" id="row-ip-proxy-layout" style="display:none;">
|
||||
<div class="ip-proxy-layout" id="ip-proxy-layout">
|
||||
<div class="ip-proxy-column ip-proxy-column-account" id="ip-proxy-account-panel">
|
||||
<div class="ip-proxy-column-header">账号密码模式</div>
|
||||
<div class="data-row ip-proxy-column-row" id="row-ip-proxy-account-list" style="display:none;">
|
||||
<span class="data-label">账号代理列表</span>
|
||||
<textarea id="input-ip-proxy-account-list" class="data-textarea mono"
|
||||
placeholder="每行一条:host:port 或 host:port:username:password 例如 global.rotgb.711proxy.com:10000:username:password"></textarea>
|
||||
</div>
|
||||
<div class="data-row ip-proxy-column-row" id="row-ip-proxy-account-session-prefix" style="display:none;">
|
||||
<span class="data-label">会话(session)</span>
|
||||
<input type="text" id="input-ip-proxy-account-session-prefix" class="data-input mono"
|
||||
placeholder="会话前缀,例如 ZC28qZ0KQL" />
|
||||
</div>
|
||||
<div class="data-row ip-proxy-column-row" id="row-ip-proxy-account-life-minutes" style="display:none;">
|
||||
<span class="data-label">时长(life)</span>
|
||||
<div class="data-inline">
|
||||
<input type="number" id="input-ip-proxy-account-life-minutes" class="data-input" min="1" max="1440" step="1"
|
||||
placeholder="5-180(分钟)" title="711Proxy 会话时长范围:5-180 分钟" />
|
||||
<span class="data-unit">分钟</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-row ip-proxy-column-row" id="row-ip-proxy-host" style="display:none;">
|
||||
<span class="data-label">代理 Host</span>
|
||||
<input type="text" id="input-ip-proxy-host" class="data-input" placeholder="例如 global.rotgb.711proxy.com" />
|
||||
</div>
|
||||
<div class="data-row ip-proxy-column-row" id="row-ip-proxy-port" style="display:none;">
|
||||
<span class="data-label">代理 Port</span>
|
||||
<input type="number" id="input-ip-proxy-port" class="data-input" min="1" max="65535" step="1"
|
||||
placeholder="例如 10000" />
|
||||
</div>
|
||||
<div class="data-row ip-proxy-column-row" id="row-ip-proxy-protocol" style="display:none;">
|
||||
<span class="data-label">代理协议</span>
|
||||
<select id="select-ip-proxy-protocol" class="data-select">
|
||||
<option value="http">HTTP</option>
|
||||
<option value="https">HTTPS</option>
|
||||
<option value="socks5">SOCKS5</option>
|
||||
<option value="socks4">SOCKS4</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="data-row ip-proxy-column-row" id="row-ip-proxy-username" style="display:none;">
|
||||
<span class="data-label">代理账号</span>
|
||||
<div class="input-with-icon">
|
||||
<input type="password" id="input-ip-proxy-username" class="data-input data-input-with-icon"
|
||||
placeholder="例如 USER047152-zone-custom-region-US-asn-ASN81" />
|
||||
<button id="btn-toggle-ip-proxy-username" class="input-icon-btn" type="button" aria-label="显示代理账号"
|
||||
title="显示代理账号"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-row ip-proxy-column-row" id="row-ip-proxy-password" style="display:none;">
|
||||
<span class="data-label">代理密码</span>
|
||||
<div class="input-with-icon">
|
||||
<input type="password" id="input-ip-proxy-password" class="data-input data-input-with-icon"
|
||||
placeholder="账号密码代理的密码" />
|
||||
<button id="btn-toggle-ip-proxy-password" class="input-icon-btn" type="button" aria-label="显示代理密码"
|
||||
title="显示代理密码"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-row ip-proxy-column-row" id="row-ip-proxy-region" style="display:none;">
|
||||
<span class="data-label">地区参数</span>
|
||||
<input type="text" id="input-ip-proxy-region" class="data-input" placeholder="可选,例如 US / DE / HK" />
|
||||
</div>
|
||||
<div class="data-row ip-proxy-column-row" id="row-ip-proxy-pool-target-count" style="display:none;">
|
||||
<span class="data-label">任务切换阈值</span>
|
||||
<div class="data-inline">
|
||||
<input type="number" id="input-ip-proxy-pool-target-count" class="data-input" min="1" max="500" step="1"
|
||||
placeholder="20(成功轮次)" title="每成功多少轮任务后自动切换一次代理;仅 1 条节点时会跳过自动切换" />
|
||||
<span class="data-unit">轮</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ip-proxy-column ip-proxy-column-api" id="ip-proxy-api-panel">
|
||||
<div class="ip-proxy-column-header">API 模式</div>
|
||||
<div class="data-row ip-proxy-column-row" id="row-ip-proxy-api-url" style="display:none;">
|
||||
<span class="data-label">代理API</span>
|
||||
<div class="input-with-icon">
|
||||
<input type="password" id="input-ip-proxy-api-url" class="data-input data-input-with-icon"
|
||||
placeholder="粘贴完整 API 链接" />
|
||||
<button id="btn-toggle-ip-proxy-api-url" class="input-icon-btn" type="button" aria-label="显示代理 API"
|
||||
title="显示代理 API"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-row" id="row-ip-proxy-actions" style="display:none;">
|
||||
<span class="data-label">切换代理</span>
|
||||
<div class="data-inline ip-proxy-actions-inline">
|
||||
<span id="ip-proxy-action-buttons" class="ip-proxy-action-grid">
|
||||
<button id="btn-ip-proxy-refresh" class="btn btn-outline btn-sm data-inline-btn" type="button">拉取</button>
|
||||
<button id="btn-ip-proxy-next" class="btn btn-outline btn-sm data-inline-btn" type="button">下一条</button>
|
||||
<button id="btn-ip-proxy-change" class="btn btn-outline btn-sm data-inline-btn" type="button" title="保持当前会话并刷新出口(仅 711 + session)">Change</button>
|
||||
<button id="btn-ip-proxy-probe" class="btn btn-outline btn-sm data-inline-btn" type="button">检测出口</button>
|
||||
</span>
|
||||
<span id="ip-proxy-action-hint" class="ip-proxy-action-hint">
|
||||
下一条:切到代理池下一条。Change:保持当前 session 重绑链路(仅 711 + session)。
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-row" id="row-ip-proxy-runtime-status" style="display:none;">
|
||||
<span class="data-label">代理状态</span>
|
||||
<div id="ip-proxy-runtime-status" class="ip-proxy-runtime-status" aria-live="polite">
|
||||
<span id="ip-proxy-runtime-dot" class="ip-proxy-runtime-dot" aria-hidden="true"></span>
|
||||
<div class="ip-proxy-runtime-content">
|
||||
<div class="ip-proxy-runtime-main">
|
||||
<span id="ip-proxy-runtime-text" class="data-value data-value-fill">未启用,沿用浏览器默认/全局代理。</span>
|
||||
</div>
|
||||
<div class="ip-proxy-runtime-meta">
|
||||
<span id="ip-proxy-current" class="ip-proxy-runtime-current mono truncate">未启用</span>
|
||||
<button id="btn-ip-proxy-check-ip" class="btn btn-outline btn-xs data-inline-btn ip-proxy-check-ip-btn" type="button">检查IP</button>
|
||||
</div>
|
||||
<details id="ip-proxy-runtime-details" class="ip-proxy-runtime-details" hidden>
|
||||
<summary>查看详细信息</summary>
|
||||
<div id="ip-proxy-runtime-details-text" class="ip-proxy-runtime-details-text"></div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-row" id="row-codex2api-url" style="display:none;">
|
||||
<span class="data-label">Codex2API</span>
|
||||
<input type="text" id="input-codex2api-url" class="data-input"
|
||||
@@ -867,6 +1024,8 @@
|
||||
<script src="mail-2925-manager.js"></script>
|
||||
<script src="icloud-manager.js"></script>
|
||||
<script src="luckmail-manager.js"></script>
|
||||
<script src="ip-proxy-provider-711proxy.js"></script>
|
||||
<script src="ip-proxy-panel.js"></script>
|
||||
<script src="contribution-mode.js"></script>
|
||||
<script src="account-records-manager.js"></script>
|
||||
<script src="sidepanel.js"></script>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user