🚀 Auto-deploy: TrackSteelAPP atualizado em 20/09/2026 01:07:33

This commit is contained in:
2026-09-20 01:07:33 +00:00
parent ce332108e8
commit c1db5c5fd1
2 changed files with 40 additions and 14 deletions
+10 -1
View File
@@ -237,7 +237,16 @@ export const ModelViewer3D: React.FC<ModelViewer3DProps> = ({
if (colorMode === 'production' && productionData) { if (colorMode === 'production' && productionData) {
// Look up production pointing status // Look up production pointing status
const prod = productionData.get(pmark); let prod = productionData.get(pmark);
if (!prod) {
// Fallback lookup: IFC marks sometimes have prefixes like B135-1-V1 or suffixes.
for (const [key, val] of productionData.entries()) {
if (pmark === key || pmark.endsWith(`-${key}`) || key.endsWith(`-${pmark}`) || pmark.includes(key)) {
prod = val;
break;
}
}
}
if (prod && prod.pointedQtd > 0) { if (prod && prod.pointedQtd > 0) {
// Apply stage color (e.g., Light Green #4ade80 for pointed) // Apply stage color (e.g., Light Green #4ade80 for pointed)
const stageHex = prod.processColor || '#4ade80'; const stageHex = prod.processColor || '#4ade80';
+30 -13
View File
@@ -48,6 +48,7 @@ export default function Visualizador3D() {
const [totalPecasBD, setTotalPecasBD] = useState<number>(0); const [totalPecasBD, setTotalPecasBD] = useState<number>(0);
const [totalApontadasBD, setTotalApontadasBD] = useState<number>(0); const [totalApontadasBD, setTotalApontadasBD] = useState<number>(0);
const [pesoTotalBD, setPesoTotalBD] = useState<number>(0); const [pesoTotalBD, setPesoTotalBD] = useState<number>(0);
const [progressoOF, setProgressoOF] = useState<number>(0);
// 3D Model and Quality State // 3D Model and Quality State
const [modelData, setModelData] = useState<LoadedIFCResult | null>(null); const [modelData, setModelData] = useState<LoadedIFCResult | null>(null);
@@ -126,8 +127,7 @@ export default function Visualizador3D() {
totalPecas += Number(p.quantidade || 0); totalPecas += Number(p.quantidade || 0);
totalPeso += Number(p.peso_total || 0); totalPeso += Number(p.peso_total || 0);
// Composite Key matching IFC (ex: B135-2-1) const key = p.marca;
const key = `${selectedOF}-${fase}-${p.marca}`;
prodMap.set(key, { prodMap.set(key, {
pecaId: p.id, pecaId: p.id,
marca: p.marca, marca: p.marca,
@@ -135,37 +135,53 @@ export default function Visualizador3D() {
totalQtd: Number(p.quantidade || 1), totalQtd: Number(p.quantidade || 1),
pointedQtd: 0, pointedQtd: 0,
currentProcessName: 'Pendente', currentProcessName: 'Pendente',
processColor: '#64748b' processColor: '#64748b',
processOrdem: 0
}); });
}); });
} }
let pointedTotal = 0;
if (apontamentosData) { if (apontamentosData) {
// Ordenar apontamentos do menor processo para o maior (assim o processo mais avançado sobressai por último)
apontamentosData.sort((a: any, b: any) => (a.processo?.ordem || 0) - (b.processo?.ordem || 0));
apontamentosData.forEach((ap: any) => { apontamentosData.forEach((ap: any) => {
const marca = ap.peca?.marca; const marca = ap.peca?.marca;
const fase = String(ap.peca?.etapa_fase || '1');
if (marca) { if (marca) {
const key = `${selectedOF}-${fase}-${marca}`; const key = marca;
const existing = prodMap.get(key); const existing = prodMap.get(key);
if (existing) { if (existing) {
const qty = Number(ap.quantidade_produzida || 0); const qty = Number(ap.quantidade_produzida || 0);
existing.pointedQtd += qty; if (qty > 0) {
pointedTotal += qty; // Atualiza a peça para o estágio mais avançado alcançado
if (ap.processo?.nome) { existing.pointedQtd = Math.max(existing.pointedQtd, qty); // Evita duplicar apontamentos de processos anteriores
existing.currentProcessName = ap.processo.nome; existing.currentProcessName = ap.processo?.nome || existing.currentProcessName;
existing.processColor = ap.processo.cor || PROCESS_COLORS[ap.processo.nome] || '#10b981'; existing.processColor = ap.processo?.cor || PROCESS_COLORS[ap.processo?.nome || ''] || '#10b981';
existing.processOrdem = ap.processo?.ordem || existing.processOrdem;
} }
} }
} }
}); });
} }
let pointedTotal = 0;
let sumProgress = 0; // Para evolução da OF
prodMap.forEach((val) => {
pointedTotal += val.pointedQtd;
// Considerando maxOrdem = 5 como final para cálculo de %. Ajuste conforme necessário.
const pecaProgress = val.pointedQtd > 0 ? Math.min(val.processOrdem / 5, 1) * (val.pointedQtd / val.totalQtd) : 0;
sumProgress += pecaProgress * val.totalQtd;
});
const progressoGeralPercent = totalPecas > 0 ? Math.min(Math.round((sumProgress / totalPecas) * 100), 100) : 0;
setPhasesList(Array.from(phases).sort()); setPhasesList(Array.from(phases).sort());
setProductionMap(prodMap); setProductionMap(prodMap);
setTotalPecasBD(totalPecas); setTotalPecasBD(totalPecas);
setTotalApontadasBD(pointedTotal); setTotalApontadasBD(pointedTotal);
setPesoTotalBD(totalPeso); setPesoTotalBD(totalPeso);
setProgressoOF(progressoGeralPercent);
} catch (err) { } catch (err) {
console.error('Erro ao carregar dados de produção da OF:', err); console.error('Erro ao carregar dados de produção da OF:', err);
} }
@@ -201,7 +217,8 @@ export default function Visualizador3D() {
} }
}; };
const progressPercent = totalPecasBD > 0 ? Math.min(Math.round((totalApontadasBD / totalPecasBD) * 100), 100) : 0; const progressPercent = totalPecasBD > 0 ? Math.min(Math.round((totalApontadasBD / totalPecasBD) * 100), 100) : 0; // Será substituido pelo state local caso quisermos, mas o totalApontadasBD já não vai estourar.
return ( return (
<div className="flex flex-col h-[calc(100vh-4rem)] p-4 md:p-6 space-y-4 max-w-[1920px] mx-auto overflow-hidden"> <div className="flex flex-col h-[calc(100vh-4rem)] p-4 md:p-6 space-y-4 max-w-[1920px] mx-auto overflow-hidden">
@@ -346,7 +363,7 @@ export default function Visualizador3D() {
Evolução da OF Evolução da OF
</span> </span>
<span className="text-lg font-mono font-extrabold text-amber-400"> <span className="text-lg font-mono font-extrabold text-amber-400">
{progressPercent}% concluído {progressoOF}% concluído
</span> </span>
</div> </div>
<TrendingUp className="w-5 h-5 text-amber-400" /> <TrendingUp className="w-5 h-5 text-amber-400" />