feat: 홈 일별 캘린더·시세 갱신·게시판 카테고리·약관동의·계좌 마스킹
- 홈: 6월 예산 아래 일별 수입/지출 캘린더(마우스오버/탭 시 내역 목록) - 투자: 시세 자동조회 버튼/진입 시 갱신, 보유종목 2줄 표기, 평가액 직접입력 - 게시판: 커뮤니티/짠테크 수다방/재테크 팁 분리, 사이드바 영역 구분선 - 회원가입: 이용약관·개인정보 수집 동의(필수 체크) - 보안: 계좌번호 화면 마스킹(끝 4자리+눈 토글) - 정기→고정지출, 내역/정기 라디오·sticky 저장, 태그 드래그 정렬 - fix: 모바일웹 새로고침 시 로그인 팝업(restore localStorage 우선) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import { useRoute, useRouter } from 'vue-router'
|
||||
import { boardApi } from '@/api/boardApi'
|
||||
import { formatRelative } from '@/utils/datetime'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { boardLabel, DEFAULT_BOARD } from '@/constants/boards'
|
||||
import IconBtn from '@/components/ui/IconBtn.vue'
|
||||
|
||||
const route = useRoute()
|
||||
@@ -11,6 +12,10 @@ const router = useRouter()
|
||||
const auth = useAuthStore()
|
||||
const isAdmin = computed(() => auth.user?.role === 'ADMIN')
|
||||
|
||||
// 현재 게시판(카테고리)
|
||||
const category = computed(() => route.params.category || DEFAULT_BOARD)
|
||||
const boardTitle = computed(() => boardLabel(category.value))
|
||||
|
||||
const posts = ref([])
|
||||
const tags = ref([])
|
||||
const loading = ref(false)
|
||||
@@ -38,6 +43,7 @@ async function load() {
|
||||
error.value = null
|
||||
try {
|
||||
const res = await boardApi.list({
|
||||
category: category.value,
|
||||
page: page.value,
|
||||
size: size.value,
|
||||
tag: activeTag.value,
|
||||
@@ -107,14 +113,9 @@ function clearSearch() {
|
||||
pushQuery({ page: 1, tag: activeTag.value })
|
||||
}
|
||||
|
||||
// 목록 표시 순번: 전체건수 기준 내림차순 (최신글이 큰 번호)
|
||||
function rowNumber(index) {
|
||||
return totalElements.value - (page.value - 1) * size.value - index
|
||||
}
|
||||
|
||||
// 쿼리가 바뀔 때마다(검색·페이지 이동·뒤로가기 포함) 상태 동기화 후 재조회
|
||||
// 경로(게시판 전환)·쿼리(검색·페이지·뒤로가기)가 바뀌면 상태 동기화 후 재조회
|
||||
watch(
|
||||
() => route.query,
|
||||
() => route.fullPath,
|
||||
() => {
|
||||
syncFromQuery()
|
||||
load()
|
||||
@@ -128,8 +129,8 @@ onMounted(loadTags)
|
||||
<template>
|
||||
<section class="board">
|
||||
<header class="board-head">
|
||||
<h1>자유게시판</h1>
|
||||
<IconBtn icon="edit" title="글쓰기" variant="primary" @click="router.push('/board/write')" />
|
||||
<h1>{{ boardTitle }}</h1>
|
||||
<IconBtn icon="edit" title="글쓰기" variant="primary" @click="router.push(`/board/${category}/write`)" />
|
||||
</header>
|
||||
|
||||
<div v-if="tags.length" class="tag-filter">
|
||||
@@ -155,7 +156,6 @@ onMounted(loadTags)
|
||||
<table v-else-if="posts.length" class="post-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-id">번호</th>
|
||||
<th>제목</th>
|
||||
<th class="col-author">작성자</th>
|
||||
<th class="col-num">조회</th>
|
||||
@@ -163,8 +163,7 @@ onMounted(loadTags)
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(p, index) in posts" :key="p.id" @click="router.push(`/board/${p.id}`)">
|
||||
<td class="col-id">{{ rowNumber(index) }}</td>
|
||||
<tr v-for="p in posts" :key="p.id" @click="router.push(`/board/${category}/${p.id}`)">
|
||||
<td>
|
||||
<template v-if="p.blocked && !isAdmin">
|
||||
<span class="blocked-msg">🚫 관리자에 의해 제한된 게시글입니다.</span>
|
||||
@@ -291,7 +290,6 @@ button:disabled {
|
||||
.post-table tbody tr:hover {
|
||||
background: var(--color-background-soft);
|
||||
}
|
||||
.col-id,
|
||||
.col-num {
|
||||
width: 60px;
|
||||
text-align: center;
|
||||
@@ -440,20 +438,14 @@ button:disabled {
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
/* 제목(2번째 셀): 첫 줄 전체 */
|
||||
.post-table td:nth-child(2) {
|
||||
/* 제목(첫 번째 셀): 첫 줄 전체 */
|
||||
.post-table td:nth-child(1) {
|
||||
order: 0;
|
||||
width: 100% !important;
|
||||
font-size: 0.97rem;
|
||||
opacity: 1;
|
||||
font-weight: 500;
|
||||
}
|
||||
.post-table .col-id {
|
||||
order: 1;
|
||||
}
|
||||
.post-table .col-id::before {
|
||||
content: '#';
|
||||
}
|
||||
.post-table .col-author {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user