From 4e6a89fd7a6d5e103a2d3bd9d43a6b13361d0899 Mon Sep 17 00:00:00 2001 From: ByungCheol Date: Thu, 4 Jun 2026 05:01:33 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=ED=99=88=20=EC=9D=BC=EB=B3=84=20?= =?UTF-8?q?=EC=BA=98=EB=A6=B0=EB=8D=94=C2=B7=EC=8B=9C=EC=84=B8=20=EA=B0=B1?= =?UTF-8?q?=EC=8B=A0=C2=B7=EA=B2=8C=EC=8B=9C=ED=8C=90=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=C2=B7=EC=95=BD=EA=B4=80=EB=8F=99=EC=9D=98?= =?UTF-8?q?=C2=B7=EA=B3=84=EC=A2=8C=20=EB=A7=88=EC=8A=A4=ED=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 홈: 6월 예산 아래 일별 수입/지출 캘린더(마우스오버/탭 시 내역 목록) - 투자: 시세 자동조회 버튼/진입 시 갱신, 보유종목 2줄 표기, 평가액 직접입력 - 게시판: 커뮤니티/짠테크 수다방/재테크 팁 분리, 사이드바 영역 구분선 - 회원가입: 이용약관·개인정보 수집 동의(필수 체크) - 보안: 계좌번호 화면 마스킹(끝 4자리+눈 토글) - 정기→고정지출, 내역/정기 라디오·sticky 저장, 태그 드래그 정렬 - fix: 모바일웹 새로고침 시 로그인 팝업(restore localStorage 우선) Co-Authored-By: Claude Opus 4.8 --- src/api/accountApi.js | 9 + src/api/boardApi.js | 3 +- src/components/SignupModal.vue | 117 ++++++++++- src/components/layout/AppSidebar.vue | 36 ++-- src/constants/boards.js | 19 ++ src/constants/terms.js | 58 ++++++ src/router/index.js | 12 +- src/stores/auth.js | 33 ++-- src/views/HomeView.vue | 230 +++++++++++++++++++++- src/views/account/AccountTagView.vue | 59 +++++- src/views/account/AccountView.vue | 100 +++++++--- src/views/account/AccountWalletView.vue | 97 +++++++++- src/views/account/InvestPortfolio.vue | 88 ++++++++- src/views/account/RecurringView.vue | 245 ++++++++++++++++++++---- src/views/board/BoardDetailView.vue | 9 +- src/views/board/BoardListView.vue | 34 ++-- src/views/board/BoardWriteView.vue | 9 +- 17 files changed, 1022 insertions(+), 136 deletions(-) create mode 100644 src/constants/boards.js create mode 100644 src/constants/terms.js diff --git a/src/api/accountApi.js b/src/api/accountApi.js index 8e0dd63..fefbe58 100644 --- a/src/api/accountApi.js +++ b/src/api/accountApi.js @@ -109,6 +109,12 @@ export const accountApi = { removeHolding(id) { return http.delete(`/account/invest/holdings/${id}`) }, + refreshPrices(walletId) { + return http.post('/account/invest/holdings/refresh-prices', null, { params: { walletId } }) + }, + refreshAllPrices() { + return http.post('/account/invest/refresh-prices') + }, holdingTrades(holdingId) { return http.get(`/account/invest/holdings/${holdingId}/trades`) }, @@ -152,6 +158,9 @@ export const accountApi = { removeTag(id) { return http.delete(`/account/tags/${id}`) }, + reorderTags(ids) { + return http.put('/account/tags/reorder', { ids }) + }, // 카드 결제 알림 자동인식 (미확인 내역) pendingCount() { diff --git a/src/api/boardApi.js b/src/api/boardApi.js index 8efca36..ef0b725 100644 --- a/src/api/boardApi.js +++ b/src/api/boardApi.js @@ -2,9 +2,10 @@ import http from './http' // 백엔드 /api/board 엔드포인트와 매핑 export const boardApi = { - list({ page = 1, size = 10, tag = '', keyword = '', searchType = '' } = {}) { + list({ category = '', page = 1, size = 10, tag = '', keyword = '', searchType = '' } = {}) { return http.get('/board/posts', { params: { + category: category || undefined, page, size, tag: tag || undefined, diff --git a/src/components/SignupModal.vue b/src/components/SignupModal.vue index 4bfe3eb..5971370 100644 --- a/src/components/SignupModal.vue +++ b/src/components/SignupModal.vue @@ -1,7 +1,8 @@ @@ -143,6 +181,17 @@ button.danger { padding: 0.4rem 0; border-bottom: 1px solid var(--color-border); } +.drag-handle { + cursor: grab; + user-select: none; + opacity: 0.5; + font-size: 1.1rem; + padding: 0 0.2rem; + touch-action: none; +} +.drag-handle:active { + cursor: grabbing; +} .tag-name { flex: 1; } diff --git a/src/views/account/AccountView.vue b/src/views/account/AccountView.vue index 672532f..0be2a7a 100644 --- a/src/views/account/AccountView.vue +++ b/src/views/account/AccountView.vue @@ -363,7 +363,7 @@ function todayStr() { function openCreate() { editId.value = null editingPending.value = false - Object.assign(form, { entryDate: todayStr(), type: 'EXPENSE', category: '', amount: null, memo: '', walletKind: '', walletId: '', toWalletKind: '', toWalletId: '', principal: null, interest: null, installmentMonths: '' }) + Object.assign(form, { entryDate: todayStr(), type: 'EXPENSE', category: '', amount: null, memo: '', walletKind: 'BANK', walletId: '', toWalletKind: '', toWalletId: '', principal: null, interest: null, installmentMonths: '' }) selectedTagIds.value = [] cancelAddCategory() formError.value = null @@ -378,7 +378,7 @@ function openEdit(e) { category: e.category || '', amount: e.amount, memo: e.memo || '', - walletKind: walletKindOf(e.walletId), + walletKind: e.walletId ? walletKindOf(e.walletId) : (e.type === 'TRANSFER' ? '' : 'CASH'), walletId: e.walletId || '', toWalletKind: walletKindOf(e.toWalletId), toWalletId: e.toWalletId || '', @@ -653,21 +653,27 @@ onMounted(async () => { - - - + + + + - +