diff --git a/backend/routes/members.js b/backend/routes/members.js index 5e91739..b5e7f3c 100644 --- a/backend/routes/members.js +++ b/backend/routes/members.js @@ -7,7 +7,7 @@ const router = express.Router(); router.get("/", async (req, res) => { try { const [rows] = await pool.query( - "SELECT id, name, name_en, birth_date, position, image_url, instagram FROM members ORDER BY id" + "SELECT id, name, birth_date, position, image_url, instagram, is_former FROM members ORDER BY is_former, birth_date" ); res.json(rows); } catch (error) { diff --git a/download_photos.sh b/download_photos.sh new file mode 100755 index 0000000..6bee747 --- /dev/null +++ b/download_photos.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# fromis_9 Photos 테이블에서 이미지 다운로드 스크립트 +# 앨범별로 폴더 분류하여 저장 + +OUTPUT_DIR="/docker/fromis_9/downloaded_photos" +mkdir -p "$OUTPUT_DIR" + +# MariaDB에서 데이터 가져오기 +docker exec mariadb mariadb -u admin -p'auddnek0403!' fromis_9 -N -e "SELECT photo_id, album_name, photo FROM Photos;" | while IFS=$'\t' read -r photo_id album_name photo_url; do + # 앨범명에서 특수문자 제거하여 폴더명 생성 + folder_name=$(echo "$album_name" | sed 's/[^a-zA-Z0-9가-힣 ]/_/g' | sed 's/ */_/g') + + # 폴더 생성 + mkdir -p "$OUTPUT_DIR/$folder_name" + + # 파일명 생성 (photo_id 기반) + filename="${photo_id}.jpg" + filepath="$OUTPUT_DIR/$folder_name/$filename" + + # 이미 다운로드된 파일은 건너뛰기 + if [ -f "$filepath" ]; then + echo "Skip: $filepath (already exists)" + continue + fi + + # 다운로드 + echo "Downloading: $album_name/$filename" + curl -s -L -o "$filepath" "$photo_url" + + # 다운로드 실패 시 삭제 + if [ ! -s "$filepath" ]; then + rm -f "$filepath" + echo "Failed: $filepath" + fi + + # Rate limiting (0.2초 대기) + sleep 0.2 +done + +echo "Download complete!" +echo "Saved to: $OUTPUT_DIR" + +# 결과 요약 +echo "" +echo "=== Summary ===" +for dir in "$OUTPUT_DIR"/*/; do + if [ -d "$dir" ]; then + count=$(ls -1 "$dir" 2>/dev/null | wc -l) + dirname=$(basename "$dir") + echo "$dirname: $count files" + fi +done diff --git a/frontend/src/pages/pc/AlbumDetail.jsx b/frontend/src/pages/pc/AlbumDetail.jsx index d92965d..878f0bb 100644 --- a/frontend/src/pages/pc/AlbumDetail.jsx +++ b/frontend/src/pages/pc/AlbumDetail.jsx @@ -318,7 +318,7 @@ function AlbumDetail() {
{member.name}
+{member.position || ''}
+{stats.debutYear}
-데뷔 연도
+2018.01.24
+데뷔일
+D+{(Math.floor((new Date() - new Date('2018-01-24')) / (1000 * 60 * 60 * 24)) + 1).toLocaleString()}
+D+Day
{stats.memberCount}
멤버 수
{stats.albumCount}
-앨범 수
-{stats.fandomName}
팬덤명
diff --git a/frontend/src/pages/pc/admin/AdminAlbumForm.jsx b/frontend/src/pages/pc/admin/AdminAlbumForm.jsx index 0261ec7..abaddcf 100644 --- a/frontend/src/pages/pc/admin/AdminAlbumForm.jsx +++ b/frontend/src/pages/pc/admin/AdminAlbumForm.jsx @@ -424,7 +424,19 @@ function AdminAlbumForm() { const handleInputChange = (e) => { const { name, value } = e.target; - setFormData(prev => ({ ...prev, [name]: value })); + + // 앨범명 변경 시 RustFS 폴더명 자동 생성 + if (name === 'title') { + const folderName = value + .toLowerCase() + .replace(/[\s.]+/g, '-') // 띄어쓰기, 점을 하이픈으로 + .replace(/[^a-z0-9가-힣-]/g, '') // 특수문자 제거 (영문, 숫자, 한글, 하이픈만 유지) + .replace(/-+/g, '-') // 연속 하이픈 하나로 + .replace(/^-|-$/g, ''); // 앞뒤 하이픈 제거 + setFormData(prev => ({ ...prev, title: value, folder_name: folderName })); + } else { + setFormData(prev => ({ ...prev, [name]: value })); + } }; const handleCoverChange = (e) => { diff --git a/frontend/src/pages/pc/admin/AdminAlbumPhotos.jsx b/frontend/src/pages/pc/admin/AdminAlbumPhotos.jsx index 14e8971..1919c70 100644 --- a/frontend/src/pages/pc/admin/AdminAlbumPhotos.jsx +++ b/frontend/src/pages/pc/admin/AdminAlbumPhotos.jsx @@ -952,10 +952,16 @@ function AdminAlbumPhotos() { key={`order-${file.id}-${index}-${startNumber}`} onBlur={(e) => { const val = e.target.value.trim(); + // 스크롤 위치 저장 + const scrollY = window.scrollY; if (val && !isNaN(val)) { moveToPosition(file.id, val); } e.target.value = String(pendingFiles.findIndex(f => f.id === file.id) + 1).padStart(2, '0'); + // 스크롤 위치 복원 + requestAnimationFrame(() => { + window.scrollTo(0, scrollY); + }); }} onKeyDown={(e) => { if (e.key === 'Enter') { @@ -1010,27 +1016,51 @@ function AdminAlbumPhotos() {