refactor: 사이트 폴더명을 지역별(seoul, gyeonggi, incheon, gwangju, busan, daegu, daejeon)로 전환 및 docker-compose 반영

This commit is contained in:
2026-10-15 12:15:37 +09:00
parent a827b8e127
commit 2dcb2ae8e8
2083 changed files with 19502 additions and 574553 deletions
+141
View File
@@ -0,0 +1,141 @@
export default defineEventHandler(async (event) => {
const config = useRuntimeConfig()
const body = await readBody(event)
const {
studentName,
parentPhone,
name,
phone,
schoolName,
grade,
location,
regionName,
memo,
url
} = body || {}
const finalStudentName = studentName || name || '미기재'
const finalParentPhone = parentPhone || phone || ''
const finalLocation = location || regionName || '미기재'
const finalGrade = grade || '미지정'
const finalSchool = schoolName || '미기재'
if (!finalParentPhone) {
throw createError({
statusCode: 400,
statusMessage: '부모님 연락처를 올바르게 입력해주세요.'
})
}
const webhookUrl = config.discordWebhookUrl || 'https://discordapp.com/api/webhooks/1557204310369116210/9J4y96kmSbYNGtw5OxRgIz7InWcM8o3f8UX0Ad71-IyofwdS7tWmXkF7dj457-I8Ypiu'
const siteName = config.public.siteName || '1:1 맞춤과외'
const siteDomain = config.public.siteDomain || 'https://aeseo.cloud'
// 한국 시간 (KST)
const now = new Date()
const kstTime = new Intl.DateTimeFormat('ko-KR', {
timeZone: 'Asia/Seoul',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
}).format(now)
// 디스코드 Embed 페이로드 (이모지 완전 배제, 깔끔한 직사각형 뱃지 규격)
const discordPayload = {
username: `${siteName} 상담 알림 봇`,
avatar_url: 'https://cdn-icons-png.flaticon.com/512/2997/2997295.png',
embeds: [
{
title: `[신규 무료 상담 신청 접수] ${finalLocation} - ${finalGrade} (${finalStudentName} 학생)`,
description: `**${siteName}** 사이트에서 새로운 1:1 학습 상담 신청이 접수되었습니다.`,
color: 0x991b1b, // 신뢰감 있는 딥 레드/네이비
fields: [
{
name: "[접수 사이트]",
value: `**${siteName}**\n${siteDomain}`,
inline: true
},
{
name: "[사는 곳]",
value: finalLocation,
inline: true
},
{
name: "[학생 이름]",
value: `**${finalStudentName}**`,
inline: true
},
{
name: "[부모님 연락처]",
value: `**${finalParentPhone}**`,
inline: true
},
{
name: "[다니는 학교]",
value: finalSchool,
inline: true
},
{
name: "[학년]",
value: finalGrade,
inline: true
},
{
name: "[접수 일시 (KST)]",
value: kstTime,
inline: true
},
{
name: "[유입 페이지 URL]",
value: url ? `${url}` : `${siteDomain}`,
inline: false
},
{
name: "[상담문의 내용 (선택)]",
value: memo && memo.trim() ? memo.trim() : '입력된 상세 문의 내용 없음',
inline: false
}
],
footer: {
text: `${siteName} 실시간 상담 알림 시스템`
},
timestamp: now.toISOString()
}
]
}
try {
const res = await fetch(webhookUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(discordPayload)
})
if (!res.ok) {
const errText = await res.text()
console.error('[Discord Webhook Error]:', res.status, errText)
return {
success: false,
message: '디스코드 전송 중 오류가 발생했습니다.'
}
}
return {
success: true,
message: '상담 신청이 정상적으로 완료되었습니다.'
}
} catch (err: any) {
console.error('[Consult Submission Error]:', err.message)
return {
success: false,
message: '서버 오류로 인해 전송에 실패했습니다.'
}
}
})
+32
View File
@@ -0,0 +1,32 @@
import regionsData from '../../data/regions.json'
export default defineEventHandler((event) => {
const config = useRuntimeConfig()
const baseUrl = config.public.siteDomain || 'https://aeseo.cloud'
const list = regionsData.list as Array<{ sido: string, sigungu: string, dong: string }>
const subjects = ['영어', '수학', '국어', '통합과학', '통합사회']
const grades = ['중학생', '고등학생']
let xml = `<?xml version="1.0" encoding="UTF-8"?>\n`
xml += `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n`
// 메인
xml += ` <url>\n <loc>${baseUrl}/</loc>\n <changefreq>daily</changefreq>\n <priority>1.0</priority>\n </url>\n`
// 568개 동별 주요 과목 및 학년 URL 생성
list.forEach(r => {
// 1. 동 대표
xml += ` <url>\n <loc>${baseUrl}/${encodeURIComponent(r.dong)}</loc>\n <changefreq>weekly</changefreq>\n <priority>0.8</priority>\n </url>\n`
// 2. 동-과목-학년 대표 조합
subjects.slice(0, 3).forEach(sub => {
xml += ` <url>\n <loc>${baseUrl}/${encodeURIComponent(r.dong)}-${encodeURIComponent(grades[0])}-${encodeURIComponent(sub)}</loc>\n <changefreq>weekly</changefreq>\n <priority>0.7</priority>\n </url>\n`
})
})
xml += `</urlset>`
setHeader(event, 'content-type', 'application/xml; charset=utf-8')
return xml
})