Enhance Vereinsmeisterschaften and Vorstand pages with image support for players and board members. Implement lightbox functionality for player images in Vereinsmeisterschaften. Update CSV handling to include image filenames for better data management. Refactor components to utilize PersonCard for board members, improving code readability and maintainability.
This commit is contained in:
127
server/api/personen/upload.post.js
Normal file
127
server/api/personen/upload.post.js
Normal file
@@ -0,0 +1,127 @@
|
||||
import multer from 'multer'
|
||||
import fs from 'fs/promises'
|
||||
import path from 'path'
|
||||
import sharp from 'sharp'
|
||||
import { getUserFromToken, verifyToken } from '../../utils/auth.js'
|
||||
import { randomUUID } from 'crypto'
|
||||
|
||||
// Handle both dev and production paths
|
||||
const getDataPath = (filename) => {
|
||||
const cwd = process.cwd()
|
||||
if (cwd.endsWith('.output')) {
|
||||
return path.join(cwd, '../server/data', filename)
|
||||
}
|
||||
return path.join(cwd, 'server/data', filename)
|
||||
}
|
||||
|
||||
const PERSONEN_DIR = getDataPath('personen')
|
||||
|
||||
// Multer-Konfiguration für Bild-Uploads
|
||||
const storage = multer.diskStorage({
|
||||
destination: async (req, file, cb) => {
|
||||
try {
|
||||
await fs.mkdir(PERSONEN_DIR, { recursive: true })
|
||||
cb(null, PERSONEN_DIR)
|
||||
} catch (error) {
|
||||
cb(error)
|
||||
}
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
const ext = path.extname(file.originalname)
|
||||
const filename = `${randomUUID()}${ext}`
|
||||
cb(null, filename)
|
||||
}
|
||||
})
|
||||
|
||||
const upload = multer({
|
||||
storage,
|
||||
fileFilter: (req, file, cb) => {
|
||||
const allowedMimes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp']
|
||||
if (allowedMimes.includes(file.mimetype)) {
|
||||
cb(null, true)
|
||||
} else {
|
||||
cb(new Error('Nur Bilddateien sind erlaubt (JPEG, PNG, GIF, WebP)'), false)
|
||||
}
|
||||
},
|
||||
limits: {
|
||||
fileSize: 10 * 1024 * 1024 // 10MB Limit
|
||||
}
|
||||
})
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
try {
|
||||
// Authentifizierung prüfen
|
||||
const token = getCookie(event, 'auth_token') || getHeader(event, 'authorization')?.replace('Bearer ', '')
|
||||
|
||||
if (!token) {
|
||||
throw createError({
|
||||
statusCode: 401,
|
||||
statusMessage: 'Nicht authentifiziert'
|
||||
})
|
||||
}
|
||||
|
||||
const decoded = verifyToken(token)
|
||||
if (!decoded) {
|
||||
throw createError({
|
||||
statusCode: 401,
|
||||
statusMessage: 'Ungültiges Token'
|
||||
})
|
||||
}
|
||||
|
||||
const user = await getUserFromToken(token)
|
||||
if (!user || (user.role !== 'admin' && user.role !== 'vorstand')) {
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage: 'Keine Berechtigung zum Hochladen von Bildern'
|
||||
})
|
||||
}
|
||||
|
||||
// Multer-Middleware für multipart/form-data
|
||||
await new Promise((resolve, reject) => {
|
||||
upload.single('image')(event.node.req, event.node.res, (err) => {
|
||||
if (err) reject(err)
|
||||
else resolve()
|
||||
})
|
||||
})
|
||||
|
||||
const file = event.node.req.file
|
||||
if (!file) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: 'Keine Bilddatei hochgeladen'
|
||||
})
|
||||
}
|
||||
|
||||
// Bild mit sharp verarbeiten (EXIF-Orientierung korrigieren und optional resize)
|
||||
const originalPath = file.path
|
||||
const ext = path.extname(file.originalname)
|
||||
const newFilename = `${randomUUID()}${ext}`
|
||||
const newPath = path.join(PERSONEN_DIR, newFilename)
|
||||
|
||||
// Bild verarbeiten: EXIF-Orientierung korrigieren
|
||||
await sharp(originalPath)
|
||||
.rotate()
|
||||
.toFile(newPath)
|
||||
|
||||
// Temporäre Datei löschen
|
||||
await fs.unlink(originalPath).catch(() => {})
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Bild erfolgreich hochgeladen',
|
||||
filename: newFilename
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Hochladen des Personenfotos:', error)
|
||||
|
||||
if (error.statusCode) {
|
||||
throw error
|
||||
}
|
||||
|
||||
throw createError({
|
||||
statusCode: 500,
|
||||
statusMessage: error.message || 'Fehler beim Hochladen des Bildes'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user