Atualização automática: 2026-05-23 22:02:28

This commit is contained in:
Hermes
2026-05-23 22:02:28 +00:00
parent 7cfc1724d3
commit bfa0ab4394
6 changed files with 152 additions and 14 deletions
+69 -3
View File
@@ -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' : `${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>
`;
}
}
+35
View File
@@ -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
View File
@@ -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;