This commit is contained in:
@@ -242,10 +242,15 @@ router.get('/admin/models/:id/edit', requireAdmin, (req: Request, res: Response)
|
||||
const model = q<Model>(`SELECT * FROM models WHERE id = ?`).get(req.params.id)
|
||||
if (!model) { res.redirect('/admin'); return }
|
||||
|
||||
const categories = q<Category>(`SELECT * FROM categories ORDER BY sort_order, name`).all()
|
||||
const pdfs = q<ModelPdf>(`SELECT * FROM model_pdfs WHERE model_id = ? ORDER BY sort_order`).all(model.id)
|
||||
const categories = q<Category>(`SELECT * FROM categories ORDER BY sort_order, name`).all()
|
||||
const pdfs = q<ModelPdf>(`SELECT * FROM model_pdfs WHERE model_id = ? ORDER BY sort_order`).all(model.id)
|
||||
const absModelPath = path.join(UPLOADS_DIR, model.file_path)
|
||||
const hasGeometry = (model.file_type === 'step' || model.file_type === 'stp')
|
||||
? fs.existsSync(geometryOutputPath(absModelPath))
|
||||
: true
|
||||
|
||||
res.render('admin/edit', {
|
||||
model, categories, pdfs, error: null,
|
||||
model, categories, pdfs, error: null, hasGeometry,
|
||||
baseUrl: process.env.BASE_URL ?? `http://localhost:${process.env.PORT ?? 3000}`,
|
||||
})
|
||||
})
|
||||
@@ -277,6 +282,44 @@ router.post('/admin/pdfs/:id/delete', requireAdmin, (req: Request, res: Response
|
||||
res.redirect(`/admin/models/${pdf.model_id}/edit`)
|
||||
})
|
||||
|
||||
// ---- Reconvert STEP/STP geometry -----------------------------------------
|
||||
|
||||
router.post('/admin/models/:id/reconvert', requireAdmin, async (req: Request, res: Response) => {
|
||||
const model = q<Model>(`SELECT * FROM models WHERE id = ?`).get(req.params.id)
|
||||
if (!model) { res.status(404).json({ error: 'Model not found' }); return }
|
||||
|
||||
if (model.file_type !== 'step' && model.file_type !== 'stp') {
|
||||
res.status(400).json({ error: 'Only STEP/STP models require geometry conversion' }); return
|
||||
}
|
||||
|
||||
const absModelPath = path.join(UPLOADS_DIR, model.file_path)
|
||||
if (!fs.existsSync(absModelPath)) {
|
||||
res.status(404).json({ error: 'Source model file not found on disk' }); return
|
||||
}
|
||||
|
||||
const geoOutPath = geometryOutputPath(absModelPath)
|
||||
|
||||
try {
|
||||
await convertStepFile(absModelPath, geoOutPath)
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: `Conversion failed: ${(err as Error).message}` }); return
|
||||
}
|
||||
|
||||
// Regenerate thumbnail from new geometry (non-fatal)
|
||||
try {
|
||||
const geo = JSON.parse(fs.readFileSync(geoOutPath, 'utf8')) as GeometryFile
|
||||
const tris = geometryToTriangles(geo)
|
||||
const thumbPath = thumbnailOutputPath(UPLOADS_DIR, model.id)
|
||||
await renderThumbnail(tris, thumbPath)
|
||||
const thumbRel = path.relative(UPLOADS_DIR, thumbPath).replace(/\\/g, '/')
|
||||
db.prepare(`UPDATE models SET thumbnail_path = ? WHERE id = ?`).run(thumbRel, model.id)
|
||||
} catch (thumbErr) {
|
||||
console.error('[thumbnail] reconvert thumbnail failed:', (thumbErr as Error).message)
|
||||
}
|
||||
|
||||
res.json({ ok: true })
|
||||
})
|
||||
|
||||
// ---- JSON list -----------------------------------------------------------
|
||||
|
||||
router.get('/api/admin/models', requireAdmin, (_req: Request, res: Response) => {
|
||||
|
||||
@@ -22,7 +22,11 @@ let _init: Promise<Awaited<ReturnType<typeof occtimport>>> | null = null
|
||||
|
||||
async function getOcct() {
|
||||
if (_occt) return _occt
|
||||
if (!_init) _init = occtimport().then(m => { _occt = m; return m })
|
||||
if (!_init) {
|
||||
_init = occtimport().then(m => { _occt = m; return m })
|
||||
// Reset on failure so the next upload attempt retries rather than replaying a cached rejection
|
||||
_init.catch(() => { _init = null })
|
||||
}
|
||||
return _init
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user