Finalizar estilos de acordeón y corrección de fuente

This commit is contained in:
ganglyglub2-gif
2025-11-18 12:54:19 -06:00
parent a407fc298c
commit 4974524901
3 changed files with 84 additions and 37 deletions
+3 -3
View File
@@ -237,7 +237,7 @@ session_start();
<main class="container content marco"> <main class="container content marco">
<p class="subtitulo-cotizador">Sube tu archivo .STL, selecciona la impresora y el material para obtener una cotización estimada.</p> <p class="subtitulo-cotizador">Sube tu archivo (STL, STEP, OBJ, 3MF), selecciona la impresora y el material para obtener una cotización estimada.</p>
<hr> <hr>
<form action="procesar.php" method="POST" enctype="multipart/form-data" class="formulario-cotizador"> <form action="procesar.php" method="POST" enctype="multipart/form-data" class="formulario-cotizador">
@@ -255,8 +255,8 @@ session_start();
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="stl_file" class="font-weight-bold">Sube tu archivo STL:</label> <label for="stl_file" class="font-weight-bold">Sube tu archivo (STL, STEP, OBJ, 3MF):</label>
<input type="file" name="stl_file" id="stl_file" class="form-control-file" accept=".stl" required> <input type="file" name="stl_file" id="stl_file" class="form-control-file" accept=".stl,.step,.stp,.obj,.3mf" required>
</div> </div>
<div class="text-center"> <div class="text-center">
+7 -4
View File
@@ -27,7 +27,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
echo '<div class="alert alert-danger">No se pudo leer la información del G-code.</div>'; echo '<div class="alert alert-danger">No se pudo leer la información del G-code.</div>';
exit; exit;
} }
// Capturamos el nombre del STL final (por si hubo conversión)
$nombreArchivoFinal = $result['finalStl'] ?? basename($stlPath);
// Datos del archivo // Datos del archivo
$margen = 0.10; $margen = 0.10;
$filamento_mm = $result['filamentUsedMm'] ?? 0; $filamento_mm = $result['filamentUsedMm'] ?? 0;
@@ -152,7 +154,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
</div> </div>
<hr>'; <hr>';
// ========= 2. BLOQUE DE ACORDEONES (REESTRUCTURADO LADO A LADO) ========= // ========= 2. BLOQUE DE ACORDEONES =========
echo ' echo '
<div class="row accordion-custom"> <div class="row accordion-custom">
@@ -227,8 +229,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
</div> </div>
'; ';
// === DIV OCULTO === // === DIV OCULTO
$stlUrl = 'uploads/' . htmlspecialchars(basename($stlPath));
$stlUrl = 'uploads/' . htmlspecialchars($nombreArchivoFinal);
echo '<div id="stl-data-url" data-url="' . $stlUrl . '" style="display: none;"></div>'; echo '<div id="stl-data-url" data-url="' . $stlUrl . '" style="display: none;"></div>';
+74 -30
View File
@@ -1,44 +1,88 @@
const { exec } = require('child_process'); const { execFile } = require('child_process');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const stlFile = process.argv[2]; // Argumentos
if (!stlFile || !fs.existsSync(stlFile)) { const inputFile = process.argv[2];
console.error(JSON.stringify({ error: 'Archivo STL no encontrado' })); const profileName = process.argv[3];
// Validaciones iniciales
if (!inputFile || !fs.existsSync(inputFile)) {
console.error(JSON.stringify({ error: 'Archivo no encontrado' }));
process.exit(1); process.exit(1);
} }
const gcodeFile = stlFile.replace(/\.stl$/i, '.gcode'); // Ruta al binario de PrusaSlicer
const prusaPath = '/app/squashfs-root/squashfs-root/usr/bin/prusa-slicer';
// Ruta al perfil de PrusaSlicer // Función principal asíncrona para manejar el flujo paso a paso
const profilePath = '/app/profiles/Ender3_Bltouch.ini'; async function procesarArchivo() {
try {
let stlFile = inputFile;
const ext = path.extname(inputFile).toLowerCase();
// 1. SI NO ES STL, LO CONVERTIMOS
if (ext !== '.stl') {
// Creamos un nombre para el nuevo STL (ej: archivo.step -> archivo.stl)
const convertedStl = inputFile.substring(0, inputFile.lastIndexOf('.')) + '.stl';
// Comando de conversión: prusa-slicer --export-stl -o archivo.stl archivo.step
await new Promise((resolve, reject) => {
execFile(prusaPath, ['--export-stl', '-o', convertedStl, inputFile], (error, stdout, stderr) => {
if (error) reject(`Error convirtiendo a STL: ${stderr || error.message}`);
else resolve();
});
});
// Ahora usamos el nuevo archivo convertido para todo lo demás
stlFile = convertedStl;
}
// Ruta absoluta del binario // 2. PREPARAMOS EL G-CODE
const prusaCmd = `/app/squashfs-root/squashfs-root/usr/bin/prusa-slicer --export-gcode -o ${gcodeFile} --load ${profilePath} ${stlFile}`; const gcodeFile = stlFile.replace(/\.stl$/i, '.gcode');
// Perfil de impresora (Fallback si no se envía)
const profilePath = profileName
? `/app/profiles/${profileName}`
: '/app/profiles/Ender3_Bltouch.ini';
exec(prusaCmd, (error, stdout, stderr) => { if (!fs.existsSync(profilePath)) {
if (error) { throw new Error(`Perfil no encontrado: ${profilePath}`);
console.error(JSON.stringify({ error: `Error al generar G-code: ${error.message}`, stderr })); }
return;
}
if (!fs.existsSync(gcodeFile)) { // 3. GENERAMOS EL G-CODE (Usando el STL, sea el original o el convertido)
console.error(JSON.stringify({ error: 'No se generó el archivo G-code' })); await new Promise((resolve, reject) => {
return; const prusaArgs = ['--export-gcode', '-o', gcodeFile, '--load', profilePath, stlFile];
} execFile(prusaPath, prusaArgs, (error, stdout, stderr) => {
if (error) reject(`Error generando G-code: ${stderr || error.message}`);
else resolve();
});
});
const gcodeContent = fs.readFileSync(gcodeFile, 'utf-8'); if (!fs.existsSync(gcodeFile)) {
throw new Error('No se generó el archivo G-code');
}
const filamentMatchMm = gcodeContent.match(/filament used \[mm\] = ([0-9.]+)/i); // 4. LEEMOS RESULTADOS
const filamentMatchCm3 = gcodeContent.match(/filament used \[cm3\] = ([0-9.]+)/i); const gcodeContent = fs.readFileSync(gcodeFile, 'utf-8');
const timeMatch = gcodeContent.match(/estimated printing time .* = ([0-9hms ]+)/i); const filamentMatchMm = gcodeContent.match(/filament used \[mm\] = ([0-9.]+)/i);
const filamentMatchCm3 = gcodeContent.match(/filament used \[cm3\] = ([0-9.]+)/i);
const timeMatch = gcodeContent.match(/estimated printing time .* = ([0-9hms ]+)/i);
const result = { // 5. ENVIAMOS LA RESPUESTA
gcodeFile, // Importante: Devolvemos 'finalStl' para que PHP sepa qué archivo mostrar en el visor
filamentUsedMm: filamentMatchMm ? parseFloat(filamentMatchMm[1]) : null, console.log(JSON.stringify({
filamentUsedCm3: filamentMatchCm3 ? parseFloat(filamentMatchCm3[1]) : null, gcodeFile: gcodeFile,
estimatedTime: timeMatch ? timeMatch[1].trim() : null finalStl: path.basename(stlFile), // <--- ESTO ES CLAVE PARA EL VISOR
}; filamentUsedMm: filamentMatchMm ? parseFloat(filamentMatchMm[1]) : 0,
filamentUsedCm3: filamentMatchCm3 ? parseFloat(filamentMatchCm3[1]) : 0,
estimatedTime: timeMatch ? timeMatch[1].trim() : "0h 0m 0s"
}));
console.log(JSON.stringify(result)); } catch (err) {
}); console.error(JSON.stringify({ error: err.message }));
process.exit(1);
}
}
procesarArchivo();