관리자 기능과 계정 즐겨찾기 개선

This commit is contained in:
2026-06-23 14:32:43 +09:00
parent 00e05dbe3f
commit 93e81ce3ea
26 changed files with 804 additions and 914 deletions

View File

@@ -53,3 +53,59 @@ export function getPreviewUrl(shareCode, previewImageRecord = null) {
}
return null;
}
/**
* 공유 코드에 연결된 미리보기 파일 삭제
* @param {string} shareCode
* @returns {boolean}
*/
export function deletePreviewImage(shareCode) {
const filePath = path.join(getPreviewsDir(), `${shareCode}.png`);
if (!fs.existsSync(filePath)) return false;
try {
fs.unlinkSync(filePath);
return true;
} catch (err) {
console.warn(`[preview] 삭제 실패: ${filePath}`, err);
return false;
}
}
/**
* DB에서 참조하지 않는 미리보기 파일 목록
* @param {Iterable<string>} referencedShareCodes
* @returns {Array<{fileName: string, size: number, modifiedAt: string}>}
*/
export function listOrphanPreviewImages(referencedShareCodes) {
const referenced = new Set([...referencedShareCodes].map((code) => `${code}.png`));
return fs
.readdirSync(getPreviewsDir(), { withFileTypes: true })
.filter((entry) => entry.isFile() && entry.name.toLowerCase().endsWith('.png'))
.filter((entry) => !referenced.has(entry.name))
.map((entry) => {
const stat = fs.statSync(path.join(getPreviewsDir(), entry.name));
return {
fileName: entry.name,
size: stat.size,
modifiedAt: stat.mtime.toISOString(),
};
})
.sort((a, b) => b.modifiedAt.localeCompare(a.modifiedAt));
}
/**
* 미참조 미리보기 파일 일괄 삭제
* @param {Iterable<string>} referencedShareCodes
* @returns {{deletedCount: number, deletedBytes: number}}
*/
export function deleteOrphanPreviewImages(referencedShareCodes) {
const orphans = listOrphanPreviewImages(referencedShareCodes);
let deletedBytes = 0;
orphans.forEach((file) => {
fs.unlinkSync(path.join(getPreviewsDir(), file.fileName));
deletedBytes += file.size;
});
return { deletedCount: orphans.length, deletedBytes };
}