방식 개편

This commit is contained in:
2026-11-05 14:07:55 +09:00
parent 6d78eccb65
commit 67a7fa0326
156 changed files with 107591 additions and 12747 deletions
+88 -63
View File
@@ -17,7 +17,7 @@
</p>
</div>
<!-- 2 - 2 - 1 그리드 정렬 레이아웃 -->
<!-- 가로 1열 5칸 캐러셀 레이아웃 -->
<div class="subject-grid-221">
<div
v-for="(item, idx) in subjectList"
@@ -26,17 +26,18 @@
:class="`card-item-${idx + 1}`"
@click="openModal(item)"
>
<div class="card-inner">
<figure class="card-inner m-0">
<div class="img-wrap">
<img
:src="item.image"
:alt="`${item.name} 1:1 맞춤 지도`"
width="600"
height="600"
:src="item.path"
:alt="`${shortSido || defaultSido} ${gradeShort || computedGradeShort} ${item.keyName} 과외 · ${regionDong || defaultDong} ${item.name}`"
width="1080"
height="1080"
decoding="async"
class="subject-img"
loading="lazy"
loading="eager"
fetchpriority="high"
/>
<span class="subject-tag">{{ item.tag }}</span>
<div class="zoom-overlay">
<span class="zoom-btn">
<i class="fa-solid fa-magnifying-glass-plus"></i>
@@ -45,18 +46,18 @@
</div>
</div>
<div class="card-info">
<figcaption class="card-info">
<div class="card-subject-name">
<span class="sub-name">{{ item.name }}</span>
<h3 class="sub-name m-0 text-inherit font-extrabold">{{ shortSido || defaultSido }} {{ gradeShort || computedGradeShort }} {{ item.name }}</h3>
<span class="sub-grade">{{ grade }}</span>
</div>
<p class="card-subject-desc">{{ item.desc }}</p>
<div class="card-action">
<NuxtLink :to="getSubjectPageUrl(item.subjectKey)" class="card-action" @click.stop>
<span>자세히 보기 & 신청</span>
<i class="fa-solid fa-arrow-right"></i>
</div>
</div>
</div>
</NuxtLink>
</figcaption>
</figure>
</div>
</div>
@@ -87,13 +88,13 @@
<!-- 모달 좌측: 고해상도 생성 이미지 원본 -->
<div class="modal-img-col">
<img
:src="selectedItem.image"
:alt="`${selectedItem.name} 1:1 맞춤 과외`"
width="600"
height="600"
:src="selectedItem.path"
:alt="`${shortSido || defaultSido} ${gradeShort || computedGradeShort} ${selectedItem.keyName} 과외`"
width="1080"
height="1080"
decoding="async"
class="modal-main-img"
/>
<span class="modal-img-badge">{{ selectedItem.tag }}</span>
</div>
<!-- 모달 우측: 상세 설명 및 액션 버튼 -->
@@ -148,7 +149,7 @@
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
const props = defineProps({
@@ -156,9 +157,17 @@ const props = defineProps({
type: String,
default: ''
},
shortSido: {
type: String,
default: '인천'
},
grade: {
type: String,
default: '중·고등'
default: '중학생'
},
gradeShort: {
type: String,
default: ''
},
currentSubject: {
type: String,
@@ -167,15 +176,21 @@ const props = defineProps({
})
const router = useRouter()
const defaultDong = '송도동'
const defaultSido = '인천'
const computedGradeShort = computed(() => {
if (props.gradeShort) return props.gradeShort
return (props.grade || '').includes('초등') ? '초등' : (props.grade || '').includes('고등') ? '고등' : '중등'
})
const config = useRuntimeConfig()
const siteDomain = config.public?.siteDomain || 'https://aeseo.cloud'
const siteDomain = config.public?.siteDomain || 'https://aeseo.site'
// 5대 핵심 과목 (2 2 1 순서 배치)
// 5대 핵심 과목 (가로 1열 5칸 캐러셀 배치)
const subjectList = [
// 1행: 수학, 영어
{
name: '수학과외',
keyName: '수학',
subjectKey: 'math',
tag: '인기 1위',
image: `${siteDomain}/img/math-tutoring.png`,
@@ -190,6 +205,7 @@ const subjectList = [
},
{
name: '영어과외',
keyName: '영어',
subjectKey: 'english',
tag: '내신 필수',
image: `${siteDomain}/img/english-tutoring.png`,
@@ -202,9 +218,9 @@ const subjectList = [
{ title: '1:1 구문 독해 & 빈칸 추론 특훈', desc: '문장 구조 분석을 통해 킬러 빈칸·순서 배열 문제를 빠르고 정확히 풉니다.' }
]
},
// 2행: 국어, 과학
{
name: '국어과외',
keyName: '국어',
subjectKey: 'korean',
tag: '문해력 완성',
image: `${siteDomain}/img/korean-tutoring.png`,
@@ -219,6 +235,7 @@ const subjectList = [
},
{
name: '과학과외',
keyName: '과학',
subjectKey: 'science',
tag: '통합과학',
image: `${siteDomain}/img/science-tutoring.png`,
@@ -231,9 +248,9 @@ const subjectList = [
{ title: '수행평가 실험 보고서 1:1 가이드', desc: '지필고사뿐 아니라 감점되기 쉬운 과학 탐구 보고서 만점을 케어합니다.' }
]
},
// 3행: 사회 (1개 단독 센터 정렬)
{
name: '사회과외',
keyName: '사회',
subjectKey: 'social',
tag: '통합사회',
image: `${siteDomain}/img/social-studies-tutoring.png`,
@@ -304,8 +321,9 @@ const applyWithSubject = (subjectName) => {
// 해당 과목 전용 페이지 URL 생성 (NuxtLink 바인딩용)
const getSubjectPageUrl = (subjectKey) => {
const dong = props.regionDong || '서울'
const grade = props.grade || '중학생'
const dong = props.regionDong || defaultDong
const validGrades = ['초등학생', '중학생', '고등학생']
const grade = validGrades.includes(props.grade) ? props.grade : '중학생'
const subMap = {
math: '수학',
english: '영어',
@@ -347,7 +365,7 @@ onUnmounted(() => {
<style scoped>
.subject-gallery-section {
width: 100%;
max-width: 1080px;
max-width: 1120px;
margin: 40px auto 60px;
padding: 0 16px;
position: relative;
@@ -358,7 +376,7 @@ onUnmounted(() => {
background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
border: 1px solid #e2e8f0;
border-radius: 28px;
padding: clamp(24px, 4vw, 44px) clamp(16px, 3vw, 36px);
padding: clamp(24px, 4vw, 44px) clamp(16px, 3vw, 32px);
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.05);
}
@@ -398,31 +416,29 @@ onUnmounted(() => {
word-break: keep-all;
}
/* 2 - 2 - 1 그리드 레이아웃 */
/* 데스크톱: 가로 1열 5칸 균등 그리드 */
.subject-grid-221 {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
grid-template-columns: repeat(5, minmax(180px, 1fr));
gap: 14px;
width: 100%;
}
/* 5번째 아이템: 3행 단독 1개 (2열 span 및 중앙 정렬) */
.card-item-5 {
grid-column: 1 / -1;
justify-self: center;
grid-column: auto;
width: 100%;
max-width: calc(50% - 10px);
max-width: none;
}
.gallery-card {
cursor: pointer;
border-radius: 20px;
border-radius: 18px;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.card-inner {
background: #ffffff;
border-radius: 20px;
border-radius: 18px;
overflow: hidden;
border: 1px solid #e2e8f0;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.04);
@@ -459,14 +475,14 @@ onUnmounted(() => {
.subject-tag {
position: absolute;
top: 14px;
left: 14px;
top: 10px;
left: 10px;
background: rgba(15, 23, 42, 0.85);
backdrop-filter: blur(4px);
color: #ffffff;
font-size: 0.75rem;
font-size: 0.7rem;
font-weight: 800;
padding: 4px 12px;
padding: 3px 10px;
border-radius: 9999px;
z-index: 2;
}
@@ -490,9 +506,9 @@ onUnmounted(() => {
.zoom-btn {
background: #ffffff;
color: #0f172a;
font-size: 0.88rem;
font-size: 0.8rem;
font-weight: 800;
padding: 10px 18px;
padding: 8px 14px;
border-radius: 9999px;
display: inline-flex;
align-items: center;
@@ -507,7 +523,7 @@ onUnmounted(() => {
}
.card-info {
padding: 18px 20px;
padding: 14px 14px 16px;
display: flex;
flex-direction: column;
flex: 1;
@@ -516,59 +532,68 @@ onUnmounted(() => {
.card-subject-name {
display: flex;
align-items: baseline;
gap: 8px;
justify-content: space-between;
gap: 6px;
margin-bottom: 6px;
}
.sub-name {
font-size: 1.2rem;
font-size: 1.05rem;
font-weight: 800;
color: #0f172a;
}
.sub-grade {
font-size: 0.78rem;
font-size: 0.72rem;
font-weight: 700;
color: #64748b;
background: #f1f5f9;
padding: 2px 8px;
padding: 2px 7px;
border-radius: 6px;
}
.card-subject-desc {
font-size: 0.85rem;
font-size: 0.8rem;
color: #475569;
line-height: 1.45;
margin-bottom: 14px;
margin-bottom: 12px;
flex: 1;
word-break: keep-all;
}
.card-action {
font-size: 0.82rem;
font-size: 0.78rem;
font-weight: 700;
color: var(--primary-color, #1e3a8a);
display: flex;
align-items: center;
gap: 6px;
gap: 5px;
transition: gap 0.2s ease;
}
.gallery-card:hover .card-action {
gap: 10px;
gap: 9px;
}
/* 모바일 반응형 대응 */
@media (max-width: 640px) {
/* 태블릿/모바일: 가로 스크롤 캐러셀 */
@media (max-width: 1024px) {
.subject-grid-221 {
grid-template-columns: 1fr;
gap: 16px;
display: flex;
flex-wrap: nowrap;
overflow-x: auto;
scroll-snap-type: x mandatory;
gap: 12px;
padding-bottom: 12px;
-webkit-overflow-scrolling: touch;
}
.gallery-card {
flex: 0 0 220px;
scroll-snap-align: start;
}
.card-item-5 {
grid-column: auto;
max-width: 100%;
justify-self: stretch;
max-width: none;
}
}