Atualização automática: 2026-05-23 22:02:28
This commit is contained in:
@@ -59,7 +59,8 @@ function navigateToPage(page) {
|
||||
'dashboard': 'Dashboard',
|
||||
'new-clone': 'Nova Clonagem',
|
||||
'history': 'Histórico',
|
||||
'settings': 'Configurações'
|
||||
'settings': 'Configurações',
|
||||
'optimized-pages': 'Páginas Otimizadas (AI)'
|
||||
};
|
||||
document.getElementById('pageTitle').textContent = titles[page] || page;
|
||||
|
||||
@@ -70,6 +71,8 @@ function navigateToPage(page) {
|
||||
loadDashboard();
|
||||
} else if (page === 'history') {
|
||||
loadHistory();
|
||||
} else if (page === 'optimized-pages') {
|
||||
loadOptimizedPages();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,6 +209,7 @@ async function handleCloneSubmit(e) {
|
||||
const includeCSSEl = document.getElementById('includeCSS');
|
||||
const includeJSEl = document.getElementById('includeJS');
|
||||
const convertLinksEl = document.getElementById('convertLinks');
|
||||
const customFolderEl = document.getElementById('customFolder');
|
||||
|
||||
if (!cloneUrlEl || !depthLevelEl || !includeImagesEl || !includeCSSEl || !includeJSEl || !convertLinksEl) {
|
||||
console.error('Form elements not found');
|
||||
@@ -219,6 +223,7 @@ async function handleCloneSubmit(e) {
|
||||
const includeCSS = includeCSSEl.checked;
|
||||
const includeJS = includeJSEl.checked;
|
||||
const convertLinks = convertLinksEl.checked;
|
||||
const folderName = customFolderEl ? customFolderEl.value.trim() : '';
|
||||
const cloneMethod = 'wget';
|
||||
|
||||
if (!url) {
|
||||
@@ -240,6 +245,7 @@ async function handleCloneSubmit(e) {
|
||||
includeCSS,
|
||||
includeJS,
|
||||
convertLinks,
|
||||
folderName,
|
||||
method: cloneMethod
|
||||
});
|
||||
}
|
||||
@@ -306,7 +312,8 @@ async function startCloning(url, options) {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
url,
|
||||
outputDir: settings.outputDir
|
||||
outputDir: settings.outputDir,
|
||||
folderName: options.folderName
|
||||
})
|
||||
});
|
||||
} else {
|
||||
@@ -317,7 +324,8 @@ async function startCloning(url, options) {
|
||||
body: JSON.stringify({
|
||||
url,
|
||||
depth: options.depth,
|
||||
outputDir: settings.outputDir
|
||||
outputDir: settings.outputDir,
|
||||
folderName: options.folderName
|
||||
})
|
||||
});
|
||||
}
|
||||
@@ -709,3 +717,61 @@ function formatRelativeTime(dateString) {
|
||||
if (minutes > 0) return minutes === 1 ? 'Há 1 minuto' : `Há ${minutes} minutos`;
|
||||
return 'Agora mesmo';
|
||||
}
|
||||
|
||||
// Optimized Pages
|
||||
async function loadOptimizedPages() {
|
||||
const listEl = document.getElementById('optimizedList');
|
||||
if (!listEl) return;
|
||||
|
||||
listEl.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-spinner fa-spin"></i>
|
||||
<h3>Carregando...</h3>
|
||||
</div>
|
||||
`;
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/optimized-pages');
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.pages.length > 0) {
|
||||
listEl.innerHTML = data.pages.map(page => `
|
||||
<div class="clone-item">
|
||||
<div class="clone-info">
|
||||
<div class="clone-icon" style="background: linear-gradient(135deg, #ec4899 0%, #8b5cf6 100%);">
|
||||
<i class="fas fa-magic" style="color: white;"></i>
|
||||
</div>
|
||||
<div class="clone-details">
|
||||
<h4>${page.name}</h4>
|
||||
<p>Otimizada pela IA • ${page.directory}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clone-actions">
|
||||
<button class="btn btn-primary btn-sm" onclick="openClonedSite('${page.directory}')">
|
||||
<i class="fas fa-external-link-alt"></i> Visualizar
|
||||
</button>
|
||||
<button class="btn btn-secondary btn-sm" onclick="openCloneFolder('${page.directory}')">
|
||||
<i class="fas fa-folder-open"></i> Pasta
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
} else {
|
||||
listEl.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-paint-brush"></i>
|
||||
<h3>Nenhuma página otimizada encontrada</h3>
|
||||
<p>Use o Agente Designer para otimizar suas clonagens.</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
} catch (e) {
|
||||
listEl.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
<h3>Erro ao carregar</h3>
|
||||
<p>${e.message}</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,11 @@
|
||||
<span>Storage</span>
|
||||
</a>
|
||||
|
||||
<a href="#" class="nav-item" data-page="optimized-pages">
|
||||
<i class="fas fa-paint-brush"></i>
|
||||
<span>Otimizados (AI)</span>
|
||||
</a>
|
||||
|
||||
<a href="#" class="nav-item" data-page="settings">
|
||||
<i class="fas fa-cog"></i>
|
||||
<span>Configurações</span>
|
||||
@@ -150,6 +155,17 @@
|
||||
required
|
||||
>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="customFolder">
|
||||
<i class="fas fa-folder"></i> Nome Específico da Pasta (Opcional)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="customFolder"
|
||||
class="form-control"
|
||||
placeholder="ex: meu_projeto"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>
|
||||
@@ -238,6 +254,25 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Optimized Pages Page -->
|
||||
<div class="page" id="optimized-pages">
|
||||
<div class="section-header">
|
||||
<h3><i class="fas fa-paint-brush"></i> Gestão de Páginas Otimizadas pela IA</h3>
|
||||
<div class="header-actions">
|
||||
<button class="btn btn-secondary btn-sm" onclick="loadOptimizedPages()">
|
||||
<i class="fas fa-sync-alt"></i> Atualizar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clones-list" id="optimizedList">
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-spinner fa-spin"></i>
|
||||
<h3>Carregando...</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Settings Page -->
|
||||
<div class="page" id="settings">
|
||||
<div class="settings-container">
|
||||
|
||||
+32
-3
@@ -320,7 +320,7 @@ app.post('/api/wget-clone', async (req, res) => {
|
||||
|
||||
// Smart Clone Endpoint (Local Spawn)
|
||||
app.post('/api/smart-clone', (req, res) => {
|
||||
const { url } = req.body;
|
||||
const { url, folderName } = req.body;
|
||||
|
||||
if (!url) {
|
||||
return res.status(400).json({ error: 'URL is required' });
|
||||
@@ -331,9 +331,12 @@ app.post('/api/smart-clone', (req, res) => {
|
||||
|
||||
// Spawn the smart cloner process
|
||||
const scriptPath = path.join(__dirname, '..', 'simple-crawler', 'smart-cloner.js');
|
||||
console.log(`[SmartClone] Executing: node "${scriptPath}" --url="${url}"`);
|
||||
let spawnArgs = [scriptPath, `--url=${url}`];
|
||||
if (folderName) spawnArgs.push(`--folderName=${folderName}`);
|
||||
|
||||
const child = spawn('node', [scriptPath, `--url=${url}`], {
|
||||
console.log(`[SmartClone] Executing: node "${scriptPath}" --url="${url}" ${folderName ? `--folderName="${folderName}"` : ''}`);
|
||||
|
||||
const child = spawn('node', spawnArgs, {
|
||||
cwd: path.join(__dirname, '..'),
|
||||
shell: true
|
||||
});
|
||||
@@ -596,6 +599,32 @@ app.get('/index', (req, res) => {
|
||||
res.redirect('/');
|
||||
});
|
||||
|
||||
// List optimized pages
|
||||
app.get('/api/optimized-pages', (req, res) => {
|
||||
try {
|
||||
const clonesDir = path.join(__dirname, '..', 'cloned-sites');
|
||||
if (!fs.existsSync(clonesDir)) {
|
||||
return res.json({ success: true, pages: [] });
|
||||
}
|
||||
|
||||
const items = fs.readdirSync(clonesDir);
|
||||
const optimized = items
|
||||
.filter(item => {
|
||||
const fullPath = path.join(clonesDir, item);
|
||||
return fs.statSync(fullPath).isDirectory() && item.endsWith('_designer');
|
||||
})
|
||||
.map(item => ({
|
||||
name: item,
|
||||
directory: item
|
||||
}));
|
||||
|
||||
res.json({ success: true, pages: optimized });
|
||||
} catch (error) {
|
||||
console.error('Error listing optimized pages:', error);
|
||||
res.status(500).json({ success: false, error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// AI Agent Route (MiniMax)
|
||||
app.post('/api/ai/agent', async (req, res) => {
|
||||
const { systemPrompt, userMessage } = req.body;
|
||||
|
||||
Reference in New Issue
Block a user