mirror of
https://github.com/ganglyglub2-gif/cotizador-impresion-3D.git
synced 2026-07-17 18:55:11 +00:00
Finalizar estilos de acordeón y corrección de fuente
This commit is contained in:
+3
-3
@@ -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">
|
||||||
|
|||||||
+6
-3
@@ -27,6 +27,8 @@ 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;
|
||||||
@@ -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
@@ -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();
|
||||||
|
|
||||||
// Ruta absoluta del binario
|
// 1. SI NO ES STL, LO CONVERTIMOS
|
||||||
const prusaCmd = `/app/squashfs-root/squashfs-root/usr/bin/prusa-slicer --export-gcode -o ${gcodeFile} --load ${profilePath} ${stlFile}`;
|
if (ext !== '.stl') {
|
||||||
|
// Creamos un nombre para el nuevo STL (ej: archivo.step -> archivo.stl)
|
||||||
|
const convertedStl = inputFile.substring(0, inputFile.lastIndexOf('.')) + '.stl';
|
||||||
|
|
||||||
exec(prusaCmd, (error, stdout, stderr) => {
|
// Comando de conversión: prusa-slicer --export-stl -o archivo.stl archivo.step
|
||||||
if (error) {
|
await new Promise((resolve, reject) => {
|
||||||
console.error(JSON.stringify({ error: `Error al generar G-code: ${error.message}`, stderr }));
|
execFile(prusaPath, ['--export-stl', '-o', convertedStl, inputFile], (error, stdout, stderr) => {
|
||||||
return;
|
if (error) reject(`Error convirtiendo a STL: ${stderr || error.message}`);
|
||||||
}
|
else resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
if (!fs.existsSync(gcodeFile)) {
|
// Ahora usamos el nuevo archivo convertido para todo lo demás
|
||||||
console.error(JSON.stringify({ error: 'No se generó el archivo G-code' }));
|
stlFile = convertedStl;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const gcodeContent = fs.readFileSync(gcodeFile, 'utf-8');
|
// 2. PREPARAMOS EL G-CODE
|
||||||
|
const gcodeFile = stlFile.replace(/\.stl$/i, '.gcode');
|
||||||
|
|
||||||
const filamentMatchMm = gcodeContent.match(/filament used \[mm\] = ([0-9.]+)/i);
|
// Perfil de impresora (Fallback si no se envía)
|
||||||
const filamentMatchCm3 = gcodeContent.match(/filament used \[cm3\] = ([0-9.]+)/i);
|
const profilePath = profileName
|
||||||
const timeMatch = gcodeContent.match(/estimated printing time .* = ([0-9hms ]+)/i);
|
? `/app/profiles/${profileName}`
|
||||||
|
: '/app/profiles/Ender3_Bltouch.ini';
|
||||||
|
|
||||||
const result = {
|
if (!fs.existsSync(profilePath)) {
|
||||||
gcodeFile,
|
throw new Error(`Perfil no encontrado: ${profilePath}`);
|
||||||
filamentUsedMm: filamentMatchMm ? parseFloat(filamentMatchMm[1]) : null,
|
}
|
||||||
filamentUsedCm3: filamentMatchCm3 ? parseFloat(filamentMatchCm3[1]) : null,
|
|
||||||
estimatedTime: timeMatch ? timeMatch[1].trim() : null
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log(JSON.stringify(result));
|
// 3. GENERAMOS EL G-CODE (Usando el STL, sea el original o el convertido)
|
||||||
});
|
await new Promise((resolve, reject) => {
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!fs.existsSync(gcodeFile)) {
|
||||||
|
throw new Error('No se generó el archivo G-code');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. LEEMOS RESULTADOS
|
||||||
|
const gcodeContent = fs.readFileSync(gcodeFile, 'utf-8');
|
||||||
|
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);
|
||||||
|
|
||||||
|
// 5. ENVIAMOS LA RESPUESTA
|
||||||
|
// Importante: Devolvemos 'finalStl' para que PHP sepa qué archivo mostrar en el visor
|
||||||
|
console.log(JSON.stringify({
|
||||||
|
gcodeFile: gcodeFile,
|
||||||
|
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"
|
||||||
|
}));
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error(JSON.stringify({ error: err.message }));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
procesarArchivo();
|
||||||
Reference in New Issue
Block a user