fix(wbs-ux): restore vertical scrollbar in App.vue and refactor TemplateGalleryView CSS with Vanilla Scoped CSS
Validators (Pushes and Pull Requests) / UI & Storage Validation (push) Failing after 11s
Validators (Pushes and Pull Requests) / Database & Schema Validation (push) Successful in 12s
Validators (Pushes and Pull Requests) / Core Validators & Database Setup (push) Failing after 20s
Validators (Pushes and Pull Requests) / WBS & Audit Validations (push) Has been skipped
Validators (Pushes and Pull Requests) / .NET Contracts (push) Has been skipped
Validators (Pushes and Pull Requests) / Calibration & Performance (push) Has been skipped
Validators (Pushes and Pull Requests) / Operational Report & Decision Packet (push) Has been skipped
Validators (Pushes and Pull Requests) / Security & Secrets (push) Successful in 10s
Validators (Pushes and Pull Requests) / CI Workflow Lint (push) Failing after 10s
Validators (Pushes and Pull Requests) / Notify PR Results (push) Has been skipped

This commit is contained in:
2026-07-25 20:15:53 +09:00
parent 7dd174e15a
commit 02b19103db
2 changed files with 131 additions and 22 deletions
+2 -1
View File
@@ -31,10 +31,11 @@ const route = useRoute()
</div>
<main style="flex: 1; overflow: hidden; background: #F4F6F9;">
<main style="flex: 1; overflow-y: auto; background: #F4F6F9;">
<router-view />
</main>
<QuantFooter />
</div>
</template>
@@ -3,35 +3,143 @@
import { ref } from 'vue';
const templates = ref([
{ id: 'factor-detail', title: '타입 A: 마스터-디테일 스플릿', path: '/templates/factor-detail', desc: 'factor_version_history 팩터 임계값 개별 상세 제어' },
{ id: 'ag-grid-market', title: '타입 B: AG Grid 대량 편집', path: '/templates/ag-grid-market', desc: 'market_raw_history 종가 정정 및 실시간 괴리율 리액티브 연산' },
{ id: 'rebalance-pipeline', title: '타입 C: 단계별 위저드', path: '/templates/rebalance-pipeline', desc: 'decision_result_history 수동 리밸런싱 실행 파이프라인' },
{ id: 'real-dashboard', title: '타입 D: KPI 대시보드', path: '/templates/real-dashboard', desc: '포트폴리오 즉시방어 자산 비율 및 Hangfire 배치 관제' },
{ id: 'waterfall-tree', title: '타입 E: 리스크 한도 트리', path: '/templates/waterfall-tree', desc: 'order_waterfall_execution 및 shadow_ledger_history 차단 게이트 스캔' },
{ id: 'maker-checker', title: '타입 F: Maker-Checker 결재', path: '/templates/maker-checker', desc: '주요 정보 변경 시 2차 Checker 이중 승인 대기 보관함' },
{ id: 'real-rollback', title: '타입 G: 감사 이력 및 롤백', path: '/templates/real-rollback', desc: '의사결정 패킷 이력 대조 및 특정 시점 원장 롤백 복구' },
{ id: 'excel-upload', title: '타입 H: 실시간 엑셀 검증', path: '/templates/excel-upload', desc: '브라우저 내 엑셀 파싱 및 정합성 위반 셀 실시간 하이라이팅 가드' },
{ id: 'olap-export', title: '타입 I: OLAP 및 엑셀 출력', path: '/templates/olap-export', desc: 'factor_output_history 피벗 연산 및 대용량 스트리밍 xlsx 다운로드' }
{ id: 'factor-detail', title: '타입 A: 마스터-디테일 스플릿', path: '/templates/factor-detail', desc: 'factor_version_history 팩터 임계값 개별 상세 제어', typeBadge: 'Master-Detail' },
{ id: 'ag-grid-market', title: '타입 B: AG Grid 대량 편집', path: '/templates/ag-grid-market', desc: 'market_raw_history 종가 정정 및 실시간 괴리율 리액티브 연산', typeBadge: 'AG Grid' },
{ id: 'rebalance-pipeline', title: '타입 C: 단계별 위저드', path: '/templates/rebalance-pipeline', desc: 'decision_result_history 수동 리밸런싱 실행 파이프라인', typeBadge: 'Wizard' },
{ id: 'real-dashboard', title: '타입 D: KPI 대시보드', path: '/templates/real-dashboard', desc: '포트폴리오 즉시방어 자산 비율 및 Hangfire 배치 관제', typeBadge: 'KPI Card' },
{ id: 'waterfall-tree', title: '타입 E: 리스크 한도 트리', path: '/templates/waterfall-tree', desc: 'order_waterfall_execution 및 shadow_ledger_history 차단 게이트 스캔', typeBadge: 'Waterfall Tree' },
{ id: 'maker-checker', title: '타입 F: Maker-Checker 결재', path: '/templates/maker-checker', desc: '주요 정보 변경 시 2차 Checker 이중 승인 대기 보관함', typeBadge: 'Approval' },
{ id: 'real-rollback', title: '타입 G: 감사 이력 및 롤백', path: '/templates/real-rollback', desc: '의사결정 패킷 이력 대조 및 특정 시점 원장 롤백 복구', typeBadge: 'Audit-Rollback' },
{ id: 'excel-upload', title: '타입 H: 실시간 엑셀 검증', path: '/templates/excel-upload', desc: '브라우저 내 엑셀 파싱 및 정합성 위반 셀 실시간 하이라이팅 가드', typeBadge: 'Excel Parser' },
{ id: 'olap-export', title: '타입 I: OLAP 및 엑셀 출력', path: '/templates/olap-export', desc: 'factor_output_history 피벗 연산 및 대용량 스트리밍 xlsx 다운로드', typeBadge: 'OLAP Export' }
]);
</script>
<template>
<div class="p-6 bg-gray-50 min-h-screen text-sm">
<div class="mb-6">
<h2 class="text-xl font-bold text-gray-800">🛠 상용화 프로토타입 템플릿 갤러리</h2>
<p class="text-xs text-gray-500">실제 PostgreSQL 테이블 C# BFF 스트리밍 연동 로직 100% 매핑된 9 실무 템플릿 목록입니다.</p>
<div class="gallery-container">
<div class="gallery-header">
<h2 class="gallery-title">🛠 상용화 프로토타입 템플릿 갤러리</h2>
<p class="gallery-subtitle">실제 PostgreSQL 원장 스키마 C# BFF API 스트리밍이 100% 매핑된 9 실무 어드민 템플릿 표준 모음입니다.</p>
</div>
<div class="grid grid-cols-3 gap-4">
<div v-for="t in templates" :key="t.id" class="bg-white p-5 rounded border hover:shadow-md transition flex flex-col justify-between">
<div>
<h4 class="font-bold text-gray-800 text-sm mb-1">{{ t.title }}</h4>
<p class="text-xs text-gray-400 mb-4">{{ t.desc }}</p>
<div class="gallery-grid">
<div v-for="t in templates" :key="t.id" class="gallery-card">
<div class="card-body">
<div class="card-badge">{{ t.typeBadge }}</div>
<h4 class="card-title">{{ t.title }}</h4>
<p class="card-desc">{{ t.desc }}</p>
</div>
<div class="card-footer">
<router-link :to="t.path" class="btn-gallery-action">
템플릿 화면 보기
</router-link>
</div>
<router-link :to="t.path" class="text-center py-2 bg-blue-600 hover:bg-blue-700 text-white font-bold rounded text-xs block decoration-none">
템플릿 화면 보기
</router-link>
</div>
</div>
</div>
</template>
<style scoped>
.gallery-container {
padding: 24px;
background-color: #F8FAFC;
min-height: 100%;
box-sizing: border-box;
}
.gallery-header {
margin-bottom: 24px;
border-bottom: 2px solid #E2E8F0;
padding-bottom: 12px;
}
.gallery-title {
font-size: 1.25rem;
font-weight: 700;
color: #1E293B;
margin: 0 0 6px 0;
}
.gallery-subtitle {
font-size: 0.8125rem;
color: #64748B;
margin: 0;
}
.gallery-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 20px;
}
.gallery-card {
background: #FFFFFF;
border: 1px solid #CBD5E1;
border-radius: 8px;
padding: 20px;
display: flex;
flex-direction: column;
justify-content: space-between;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
transition: all 0.2s ease-in-out;
}
.gallery-card:hover {
transform: translateY(-3px);
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.1);
border-color: #2563EB;
}
.card-body {
margin-bottom: 16px;
}
.card-badge {
display: inline-block;
font-size: 0.7rem;
font-weight: 700;
color: #2563EB;
background-color: #EFF6FF;
border: 1px solid #BFDBFE;
padding: 2px 8px;
border-radius: 4px;
margin-bottom: 8px;
}
.card-title {
font-size: 0.95rem;
font-weight: 700;
color: #0F172A;
margin: 0 0 8px 0;
}
.card-desc {
font-size: 0.8rem;
color: #475569;
line-height: 1.4;
margin: 0;
}
.card-footer {
margin-top: auto;
}
.btn-gallery-action {
display: block;
width: 100%;
text-align: center;
padding: 8px 0;
background-color: #2563EB;
color: #FFFFFF;
font-size: 0.8125rem;
font-weight: 700;
text-decoration: none;
border-radius: 4px;
transition: background-color 0.15s ease;
box-sizing: border-box;
}
.btn-gallery-action:hover {
background-color: #1D4ED8;
}
</style>