ui 개편 완료

This commit is contained in:
2026-11-11 12:18:47 +09:00
parent 67a7fa0326
commit 15e8bcd37b
145 changed files with 141907 additions and 23029 deletions
+105 -26
View File
@@ -29,7 +29,7 @@
</div>
</div>
<!-- 2. 같은 동의 다른 학년 링크 -->
<!-- 2. 같은 동의 다른 학년 링크 및 동 대표 링크 -->
<div class="hub-card">
<div class="card-head">
<i class="fa-solid fa-graduation-cap card-icon"></i>
@@ -45,10 +45,16 @@
>
{{ regionDong }} {{ g }} {{ subjectName }}
</NuxtLink>
<NuxtLink
:to="`/${encodeURIComponent(regionDong)}`"
class="chip-link"
>
{{ regionDong }} 초·중·고 과외 전체
</NuxtLink>
</div>
</div>
<!-- 3. 관내 인접 동 링크 -->
<!-- 3. 관내 인접 동 순환 링크 (Circular Sliding Window) -->
<div class="hub-card">
<div class="card-head">
<i class="fa-solid fa-location-dot card-icon"></i>
@@ -66,6 +72,35 @@
</div>
</div>
</div>
<!-- 4. 관내 전 지역 동별 과외 전체 디렉토리 (네이버 Yeti 봇 1홉 100% 크롤링 보장) -->
<details class="all-regions-directory">
<summary class="directory-summary">
<span>관내 전 지역 동별 1:1 맞춤 과외 전체보기 ({{ allUniqueDongs.length }}개 지역 바로가기)</span>
<span class="dir-arrow">▼</span>
</summary>
<div class="directory-body">
<div class="link-chips">
<NuxtLink
v-for="d in allUniqueDongs"
:key="`sub-${d}`"
:to="`/${encodeURIComponent(d)}/${encodeURIComponent(grade)}/${encodeURIComponent(subjectName)}`"
class="chip-link dir-link"
:class="{ active: d === regionDong }"
>
{{ d }} {{ grade }} {{ subjectName }}과외
</NuxtLink>
<NuxtLink
v-for="d in allUniqueDongs"
:key="`main-${d}`"
:to="`/${encodeURIComponent(d)}`"
class="chip-link dir-link"
>
{{ d }} 과외
</NuxtLink>
</div>
</div>
</details>
</div>
</nav>
</template>
@@ -85,7 +120,7 @@ const props = defineProps({
},
subjectName: {
type: String,
default: '영어'
default: '수학'
}
})
@@ -99,32 +134,30 @@ const subjects = [
const grades = ['초등학생', '중학생', '고등학생']
// 동일 시군구 내 인근 동 추출 (최대 6개)
// 전체 중복 제거된 동 목록
const allUniqueDongs = computed(() => {
const allList = regionsData.list || []
return Array.from(new Set(allList.map(r => r.dong).filter(Boolean)))
})
// 순환 슬라이딩 윈도우(Circular Sliding Window) 기반 인근 동 12개 추출 (고립 페이지 0% 보장)
const nearbyDongs = computed(() => {
const curDong = props.regionDong
const allList = (regionsData.list || [])
// 현재 동의 시군구 찾기
const curRegion = allList.find(r => r.dong === curDong || r.dong.includes(curDong))
const sigungu = curRegion ? curRegion.sigungu : ''
let candidates = []
if (sigungu) {
candidates = allList
.filter(r => r.sigungu === sigungu && r.dong !== curDong)
.map(r => r.dong)
}
// 만약 동일 구의 동이 부족하면 전체에서 다른 동 가져오기
if (candidates.length < 12) {
const others = allList
.filter(r => r.dong !== curDong && !candidates.includes(r.dong))
.map(r => r.dong)
candidates = [...candidates, ...others]
}
const uniqueDongs = allUniqueDongs.value
const total = uniqueDongs.length
if (total === 0) return []
// 중복 제거 후 12개 반환
return Array.from(new Set(candidates)).slice(0, 12)
const curIdx = uniqueDongs.indexOf(curDong)
const startIdx = curIdx >= 0 ? curIdx : 0
const result = []
for (let offset = 1; offset < total && result.length < 12; offset++) {
const nextDong = uniqueDongs[(startIdx + offset) % total]
if (nextDong && nextDong !== curDong) {
result.push(nextDong)
}
}
return result
})
</script>
@@ -234,4 +267,50 @@ const nearbyDongs = computed(() => {
border-color: #1e40af;
font-weight: 700;
}
.all-regions-directory {
margin-top: 20px;
background: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 12px;
overflow: hidden;
}
.directory-summary {
padding: 14px 20px;
font-size: 0.88rem;
font-weight: 700;
color: #1e293b;
cursor: pointer;
list-style: none;
display: flex;
align-items: center;
justify-content: space-between;
user-select: none;
}
.directory-summary::-webkit-details-marker {
display: none;
}
.dir-arrow {
font-size: 0.75rem;
color: #64748b;
transition: transform 0.2s ease;
}
details[open].all-regions-directory .dir-arrow {
transform: rotate(180deg);
}
.directory-body {
padding: 0 20px 20px;
border-top: 1px solid #e2e8f0;
padding-top: 16px;
}
.dir-link {
font-size: 0.76rem;
padding: 4px 10px;
}
</style>