feat(avatars): 27 готовых пресет-аватаров + UI выбора для всех ролей
- backend/uploads/avatars/preset_01..27.png — иллюстрированные персонажи - POST /api/avatar/preset — мгновенная установка без модерации - GET /api/avatar/presets — список доступных пресетов - profile.html: галерея пресетов в модалке аватара, доступна студенту/учителю/админу - кастомная загрузка с модерацией остаётся только для студентов
This commit is contained in:
@@ -98,10 +98,49 @@ function rejectAvatar(req, res) {
|
||||
function removeAvatar(req, res) {
|
||||
const user = db.prepare('SELECT avatar_url FROM users WHERE id=?').get(req.user.id);
|
||||
if (user?.avatar_url) {
|
||||
try { fs.unlinkSync(path.join(AVATARS_DIR, user.avatar_url)); } catch {}
|
||||
if (!/^preset_\d{2}\.png$/.test(user.avatar_url)) {
|
||||
try { fs.unlinkSync(path.join(AVATARS_DIR, user.avatar_url)); } catch {}
|
||||
}
|
||||
db.prepare('UPDATE users SET avatar_url=NULL WHERE id=?').run(req.user.id);
|
||||
}
|
||||
res.json({ ok: true });
|
||||
}
|
||||
|
||||
module.exports = { requestAvatar, myStatus, getPending, approveAvatar, rejectAvatar, removeAvatar };
|
||||
/* ── GET /api/avatar/presets ── list available preset avatars ─────────────── */
|
||||
function listPresets(_req, res) {
|
||||
const files = fs.readdirSync(AVATARS_DIR)
|
||||
.filter(f => /^preset_\d{2}\.png$/.test(f))
|
||||
.sort();
|
||||
res.json({ presets: files });
|
||||
}
|
||||
|
||||
/* ── POST /api/avatar/preset ── set avatar to a preset (no moderation) ────── */
|
||||
function setPreset(req, res) {
|
||||
const filename = String(req.body.filename || '');
|
||||
if (!/^preset_\d{2}\.png$/.test(filename)) {
|
||||
return res.status(400).json({ error: 'Некорректный пресет' });
|
||||
}
|
||||
if (!fs.existsSync(path.join(AVATARS_DIR, filename))) {
|
||||
return res.status(404).json({ error: 'Пресет не найден' });
|
||||
}
|
||||
|
||||
// Remove old uploaded avatar file (but never delete preset files)
|
||||
const user = db.prepare('SELECT avatar_url FROM users WHERE id=?').get(req.user.id);
|
||||
if (user?.avatar_url && !/^preset_\d{2}\.png$/.test(user.avatar_url)) {
|
||||
try { fs.unlinkSync(path.join(AVATARS_DIR, user.avatar_url)); } catch {}
|
||||
}
|
||||
|
||||
// Cancel any pending moderation request from this user
|
||||
const prev = db.prepare(
|
||||
"SELECT filename FROM avatar_requests WHERE user_id=? AND status='pending'"
|
||||
).get(req.user.id);
|
||||
if (prev) {
|
||||
try { fs.unlinkSync(path.join(AVATARS_DIR, prev.filename)); } catch {}
|
||||
db.prepare("DELETE FROM avatar_requests WHERE user_id=? AND status='pending'").run(req.user.id);
|
||||
}
|
||||
|
||||
db.prepare('UPDATE users SET avatar_url=? WHERE id=?').run(filename, req.user.id);
|
||||
res.json({ ok: true, avatar_url: filename });
|
||||
}
|
||||
|
||||
module.exports = { requestAvatar, myStatus, getPending, approveAvatar, rejectAvatar, removeAvatar, listPresets, setPreset };
|
||||
|
||||
Reference in New Issue
Block a user