Files
ai_mip/static/js/browser.js
2026-01-13 18:59:26 +08:00

516 lines
23 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 全局变量存储当前选中的Profile和代理
let currentProfileId = null;
let currentProxyInfo = null;
// 格式化JSON显示
function formatResult(data, elementId) {
const el = document.getElementById(elementId);
el.innerHTML = `<pre style="background: #f5f5f5; padding: 12px; border-radius: 4px; overflow-x: auto; max-height: 400px;">${JSON.stringify(data, null, 2)}</pre>`;
}
// 查询Profile列表
async function listProfiles() {
try {
showToast('正在查询Profile列表...', 'info');
const response = await fetch(`${API_BASE}/api/adspower/profiles`);
const data = await response.json();
if (data.success) {
const profiles = data.data?.data?.list || [];
if (profiles.length > 0) {
// 美化显示Profile信息
let html = '<div style="background: #f5f5f5; padding: 12px; border-radius: 4px; max-height: 500px; overflow-y: auto;">';
html += `<p style="margin-bottom: 12px; font-weight: 500; color: #333;">找到 ${profiles.length} 个Profile环境</p>`;
profiles.forEach((profile, idx) => {
const proxyConfig = profile.user_proxy_config || {};
const hasProxy = proxyConfig.proxy_host && proxyConfig.proxy_port;
html += `
<div style="background: white; padding: 14px; margin-bottom: 10px; border-radius: 4px; border-left: 4px solid ${hasProxy ? '#52c41a' : '#faad14'};">
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 10px;">
<div style="flex: 1;">
<div style="font-weight: 600; color: #333; font-size: 14px; margin-bottom: 4px;">
#${idx + 1} ${profile.name}
<span style="color: #999; font-size: 12px; font-weight: 400; margin-left: 8px;">No.${profile.profile_no}</span>
</div>
<div style="color: #666; font-size: 12px;">
Profile ID: <span style="font-family: monospace; background: #f0f0f0; padding: 2px 6px; border-radius: 2px;">${profile.profile_id}</span>
</div>
</div>
<button onclick="selectProfile('${profile.profile_id}', '${profile.name}')"
style="padding: 6px 12px; background: #1890ff; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 12px; white-space: nowrap;">
选择环境
</button>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px; font-size: 12px; padding: 8px; background: #fafafa; border-radius: 3px;">
<div>
<span style="color: #999;">当前IP:</span>
<span style="color: #333; font-weight: 500; margin-left: 4px;">${profile.ip || 'N/A'}</span>
${profile.ip_country ? `<span style="color: #999; margin-left: 4px;">(${profile.ip_country.toUpperCase()})</span>` : ''}
</div>
<div>
<span style="color: #999;">最后打开:</span>
<span style="color: #666; margin-left: 4px;">${profile.last_open_time ? new Date(parseInt(profile.last_open_time) * 1000).toLocaleString('zh-CN') : 'N/A'}</span>
</div>
</div>
${hasProxy ? `
<div style="margin-top: 10px; padding: 10px; background: #f6ffed; border: 1px solid #b7eb8f; border-radius: 3px;">
<div style="font-weight: 500; color: #52c41a; margin-bottom: 6px; font-size: 12px;">✓ 代理配置</div>
<div style="font-size: 12px; color: #666; line-height: 1.6;">
<div style="display: flex; gap: 16px; flex-wrap: wrap;">
<div>
<span style="color: #999;">类型:</span>
<span style="color: #333; margin-left: 4px;">${proxyConfig.proxy_type?.toUpperCase() || 'N/A'}</span>
</div>
<div>
<span style="color: #999;">地址:</span>
<span style="color: #333; margin-left: 4px; font-family: monospace;">${proxyConfig.proxy_host}:${proxyConfig.proxy_port}</span>
</div>
${proxyConfig.latest_ip ? `
<div>
<span style="color: #999;">最新IP:</span>
<span style="color: #333; margin-left: 4px; font-family: monospace;">${proxyConfig.latest_ip}</span>
</div>
` : ''}
</div>
${proxyConfig.proxy_user ? `
<div style="margin-top: 4px;">
<span style="color: #999;">认证:</span>
<span style="color: #333; margin-left: 4px; font-family: monospace;">${proxyConfig.proxy_user}</span>
</div>
` : ''}
</div>
</div>
` : `
<div style="margin-top: 10px; padding: 8px; background: #fffbe6; border: 1px solid #ffe58f; border-radius: 3px; font-size: 12px; color: #d48806;">
⚠ 未配置代理
</div>
`}
${profile.remark ? `
<div style="margin-top: 8px; padding: 6px 8px; background: #f0f0f0; border-radius: 3px; font-size: 11px; color: #666;">
备注: ${profile.remark}
</div>
` : ''}
</div>
`;
});
html += '</div>';
document.getElementById('profileResult').innerHTML = html;
// 自动选择第一个Profile
currentProfileId = profiles[0].profile_id;
document.getElementById('profileId').value = currentProfileId;
showToast(`找到 ${profiles.length} 个Profile环境`, 'success');
} else {
document.getElementById('profileResult').innerHTML = '<p style="color: #999; text-align: center; padding: 24px;">未找到Profile环境</p>';
showToast('未找到Profile', 'info');
}
} else {
showToast(data.message || '查询失败', 'error');
}
} catch (error) {
console.error('查询Profile列表错误:', error);
showToast('查询失败: ' + error.message, 'error');
}
}
// 选择Profile
function selectProfile(profileId, profileName) {
currentProfileId = profileId;
document.getElementById('profileId').value = profileId;
showToast(`已选择环境: ${profileName}`, 'success');
}
// 启动浏览器
async function startBrowser() {
const profileId = document.getElementById('profileId').value || currentProfileId;
if (!profileId) {
showToast('请先查询Profile列表或输入Profile ID', 'error');
return;
}
try {
showToast('正在启动浏览器...', 'info');
const response = await fetch(`${API_BASE}/api/adspower/browser/start`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ user_id: profileId })
});
const data = await response.json();
if (data.success) {
formatResult(data.data, 'profileResult');
showToast('浏览器启动成功', 'success');
} else {
showToast(data.message || '启动失败', 'error');
}
} catch (error) {
showToast('启动失败: ' + error.message, 'error');
}
}
// 停止浏览器
async function stopBrowser() {
const profileId = document.getElementById('profileId').value || currentProfileId;
if (!profileId) {
showToast('请先输入Profile ID', 'error');
return;
}
try {
showToast('正在停止浏览器...', 'info');
const response = await fetch(`${API_BASE}/api/adspower/browser/stop`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ user_id: profileId })
});
const data = await response.json();
if (data.success) {
formatResult(data.data, 'profileResult');
showToast('浏览器已停止', 'success');
} else {
showToast(data.message || '停止失败', 'error');
}
} catch (error) {
showToast('停止失败: ' + error.message, 'error');
}
}
// 获取大麦IP
async function getDamaiProxy() {
try {
showToast('正在获取大麦IP...', 'info');
const response = await fetch(`${API_BASE}/api/adspower/proxy/damai`);
const data = await response.json();
if (data.success) {
currentProxyInfo = data.data;
formatResult(data.data, 'proxyResult');
showToast(`获取成功: ${data.data.host}:${data.data.port}`, 'success');
} else {
showToast(data.message || '获取失败', 'error');
}
} catch (error) {
showToast('获取失败: ' + error.message, 'error');
}
}
// 创建代理
async function createProxy() {
if (!currentProxyInfo) {
showToast('请先获取大麦IP', 'error');
return;
}
try {
showToast('正在创建代理...', 'info');
const proxyConfig = {
type: 'http',
host: currentProxyInfo.host,
port: currentProxyInfo.port,
user: '69538fdef04e1',
password: '63v0kQBr2yJXnjf',
ipchecker: 'ip2location',
remark: 'Damai Auto Proxy'
};
const response = await fetch(`${API_BASE}/api/adspower/proxy/create`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ proxy_config: proxyConfig })
});
const data = await response.json();
if (data.success) {
document.getElementById('proxyId').value = data.data.proxy_id;
formatResult(data.data, 'proxyResult');
showToast(`代理创建成功ID: ${data.data.proxy_id}`, 'success');
} else {
showToast(data.message || '创建失败', 'error');
}
} catch (error) {
showToast('创建失败: ' + error.message, 'error');
}
}
// 查询代理列表
async function listProxies() {
try {
showToast('正在查询代理列表...', 'info');
const response = await fetch(`${API_BASE}/api/adspower/proxy/list?page=1&limit=50`);
// 检查响应类型
const contentType = response.headers.get('content-type');
if (!contentType || !contentType.includes('application/json')) {
console.error('服务器返回非JSON响应:', contentType);
const text = await response.text();
console.error('响应内容:', text.substring(0, 200));
showToast('服务器响应错误,请检查后端服务', 'error');
return;
}
const data = await response.json();
if (data.success && data.data) {
const proxies = data.data?.data?.list || [];
if (proxies.length > 0) {
// 格式化显示代理信息
let html = '<div style="background: #f5f5f5; padding: 12px; border-radius: 4px; max-height: 400px; overflow-y: auto;">';
html += `<p style="margin-bottom: 12px; font-weight: 500;">找到 ${proxies.length} 个代理</p>`;
proxies.forEach((proxy, idx) => {
html += `
<div style="background: white; padding: 10px; margin-bottom: 8px; border-radius: 4px; border-left: 3px solid #1890ff;">
<div style="display: flex; justify-content: space-between; align-items: start;">
<div style="flex: 1;">
<div style="font-weight: 500; color: #333;">#${idx + 1} ID: ${proxy.proxy_id}</div>
<div style="color: #666; font-size: 13px; margin-top: 4px;">
${proxy.type} - ${proxy.host}:${proxy.port}
</div>
${proxy.remark ? `<div style="color: #999; font-size: 12px; margin-top: 2px;">备注: ${proxy.remark}</div>` : ''}
<div style="color: #999; font-size: 12px; margin-top: 2px;">
关联环境数: ${proxy.profile_count || 0}
</div>
</div>
<button onclick="document.getElementById('proxyId').value='${proxy.proxy_id}'"
style="padding: 4px 8px; background: #1890ff; color: white; border: none; border-radius: 2px; cursor: pointer; font-size: 12px;">
选择
</button>
</div>
</div>
`;
});
html += '</div>';
document.getElementById('proxyResult').innerHTML = html;
showToast(`找到 ${proxies.length} 个代理`, 'success');
} else {
document.getElementById('proxyResult').innerHTML = '<p style="color: #999; text-align: center; padding: 24px;">暂无代理,请先创建代理</p>';
showToast('暂无代理', 'info');
}
} else {
showToast(data.message || '查询失败', 'error');
document.getElementById('proxyResult').innerHTML = `<p style="color: #ff4d4f; padding: 12px;">${data.message || '查询失败'}</p>`;
}
} catch (error) {
console.error('查询代理列表错误:', error);
showToast('查询失败: ' + error.message, 'error');
document.getElementById('proxyResult').innerHTML = `<p style="color: #ff4d4f; padding: 12px;">错误: ${error.message}</p>`;
}
}
// 更新Profile代理API v2方式
async function updateProfileProxy() {
const profileId = document.getElementById('profileId').value;
const proxyId = document.getElementById('proxyId').value;
if (!profileId || !proxyId) {
showToast('请输入Profile ID和代理ID', 'error');
return;
}
try {
showToast('正在更新Profile代理 (API v2)...', 'info');
const response = await fetch(`${API_BASE}/api/adspower/profile/update`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ profile_id: profileId, proxy_id: proxyId })
});
const data = await response.json();
if (data.success) {
formatResult(data.data, 'updateResult');
showToast('更新成功 (API v2)', 'success');
} else {
showToast(data.message || '更新失败', 'error');
}
} catch (error) {
showToast('更新失败: ' + error.message, 'error');
}
}
// 更新Profile代理API v1方式
async function updateProfileProxyV1() {
const profileId = document.getElementById('profileId').value;
if (!profileId) {
showToast('请输入Profile ID', 'error');
return;
}
// 获取当前代理信息
if (!currentProxyInfo) {
showToast('请先获取大麦IP', 'error');
return;
}
try {
showToast('正在更新Profile代理 (API v1)...', 'info');
// 构建 proxy_config
const proxyConfig = {
proxy_type: 'http',
proxy_host: currentProxyInfo.host,
proxy_port: currentProxyInfo.port,
proxy_user: '69538fdef04e1',
proxy_password: '63v0kQBr2yJXnjf',
proxy_soft: 'other'
};
const response = await fetch(`${API_BASE}/api/adspower/profile/update-v1`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ profile_id: profileId, proxy_config: proxyConfig })
});
const data = await response.json();
if (data.success) {
let resultHtml = '<div style="background: #f6ffed; padding: 12px; border-radius: 4px; border: 1px solid #b7eb8f;">';
resultHtml += '<div style="color: #52c41a; font-weight: 500; margin-bottom: 8px;">✅ 代理更新成功 (API v1)</div>';
resultHtml += '<div style="font-size: 12px; color: #666;">';
resultHtml += `<div>Profile ID: ${profileId}</div>`;
resultHtml += `<div>代理地址: ${proxyConfig.proxy_host}:${proxyConfig.proxy_port}</div>`;
resultHtml += `<div>认证用户: ${proxyConfig.proxy_user}</div>`;
resultHtml += '</div></div>';
document.getElementById('updateResult').innerHTML = resultHtml;
showToast('更新成功 (API v1)', 'success');
} else {
showToast(data.message || '更新失败', 'error');
document.getElementById('updateResult').innerHTML = `<p style="color: #ff4d4f; padding: 12px;">${data.message || '更新失败'}</p>`;
}
} catch (error) {
console.error('更新Profile代理错误 (v1):', error);
showToast('更新失败: ' + error.message, 'error');
document.getElementById('updateResult').innerHTML = `<p style="color: #ff4d4f; padding: 12px;">错误: ${error.message}</p>`;
}
}
// 完整测试流程
async function fullTest(useProxy) {
const resultDiv = document.getElementById('fullTestResult');
let log = [];
function addLog(msg, type = 'info') {
const time = new Date().toLocaleTimeString();
const color = type === 'error' ? '#ff4d4f' : type === 'success' ? '#52c41a' : '#666';
log.push(`<div style="color: ${color}; margin: 4px 0;">[${time}] ${msg}</div>`);
resultDiv.innerHTML = log.join('');
}
try {
addLog('开始完整测试流程...');
// 1. 查询Profile
addLog('步骤1: 查询Profile列表');
const profileRes = await fetch(`${API_BASE}/api/adspower/profiles`);
const profileData = await profileRes.json();
if (!profileData.success) {
addLog('查询Profile失败: ' + profileData.message, 'error');
return;
}
const profiles = profileData.data?.data?.list || [];
if (profiles.length === 0) {
addLog('未找到Profile', 'error');
return;
}
currentProfileId = profiles[0].profile_id;
document.getElementById('profileId').value = currentProfileId;
addLog(`找到Profile: ${currentProfileId}`, 'success');
if (useProxy) {
// 2. 获取大麦IP
addLog('步骤2: 获取大麦IP代理');
const proxyRes = await fetch(`${API_BASE}/api/adspower/proxy/damai`);
const proxyData = await proxyRes.json();
if (!proxyData.success) {
addLog('获取代理失败: ' + proxyData.message, 'error');
return;
}
currentProxyInfo = proxyData.data;
addLog(`获取代理: ${currentProxyInfo.host}:${currentProxyInfo.port}`, 'success');
// 3. 创建代理
addLog('步骤3: 创建AdsPower代理');
const proxyConfig = {
type: 'http',
host: currentProxyInfo.host,
port: currentProxyInfo.port,
user: '69538fdef04e1',
password: '63v0kQBr2yJXnjf',
ipchecker: 'ip2location',
remark: 'Damai Auto Proxy'
};
const createProxyRes = await fetch(`${API_BASE}/api/adspower/proxy/create`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ proxy_config: proxyConfig })
});
const createProxyData = await createProxyRes.json();
if (!createProxyData.success) {
addLog('创建代理失败: ' + createProxyData.message, 'error');
return;
}
const proxyId = createProxyData.data.proxy_id;
document.getElementById('proxyId').value = proxyId;
addLog(`创建代理成功ID: ${proxyId}`, 'success');
// 4. 更新Profile
addLog('步骤4: 更新Profile代理配置');
const updateRes = await fetch(`${API_BASE}/api/adspower/profile/update`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ profile_id: currentProfileId, proxy_id: proxyId })
});
const updateData = await updateRes.json();
if (!updateData.success) {
addLog('更新Profile失败: ' + updateData.message, 'error');
return;
}
addLog('更新Profile成功', 'success');
}
// 5. 启动浏览器
addLog(`步骤${useProxy ? 5 : 2}: 启动浏览器`);
const startRes = await fetch(`${API_BASE}/api/adspower/browser/start`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ user_id: currentProfileId })
});
const startData = await startRes.json();
if (!startData.success) {
addLog('启动浏览器失败: ' + startData.message, 'error');
return;
}
addLog('浏览器启动成功', 'success');
addLog('测试流程完成!', 'success');
showToast('完整测试流程执行成功', 'success');
} catch (error) {
addLog('测试异常: ' + error.message, 'error');
showToast('测试失败: ' + error.message, 'error');
}
}