Initial commit: Add project files
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{ productName?: string; environment?: string; automationStatus?: string }>()
|
||||
</script>
|
||||
<template>
|
||||
<div class="ks-shell">
|
||||
<a class="ks-skip" href="#ks-main">본문으로 건너뛰기</a>
|
||||
<header class="ks-shell__header">
|
||||
<div><strong>{{ productName ?? 'K-ArtSell Aegis' }}</strong><small>{{ environment ?? 'IMPLEMENTATION_TEMPLATE' }}</small></div>
|
||||
<div class="ks-shell__boundary" role="status">{{ automationStatus ?? '투자자문형 · 자동주문/KIS 제출 OFF · 자동 모델승격 OFF' }}</div>
|
||||
<slot name="header-actions" />
|
||||
</header>
|
||||
<aside class="ks-shell__nav" aria-label="주요 메뉴"><slot name="navigation" /></aside>
|
||||
<main id="ks-main" class="ks-shell__main" tabindex="-1"><slot /></main>
|
||||
<footer class="ks-shell__footer"><slot name="footer">RESEARCH_CANDIDATE_NOT_PRODUCTION</slot></footer>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.ks-shell { min-height: 100vh; display: grid; grid-template-columns: 16rem minmax(0, 1fr); grid-template-rows: auto 1fr auto; grid-template-areas: 'header header' 'nav main' 'footer footer'; }
|
||||
.ks-shell__header { grid-area: header; display: flex; align-items: center; justify-content: space-between; gap: var(--ks-space-4); padding: var(--ks-space-3) var(--ks-space-6); color: #fff; background: var(--ks-color-neutral-950); }
|
||||
.ks-shell__header > div:first-child { display: grid; } .ks-shell__header small { color: #cbd5e1; }
|
||||
.ks-shell__boundary { padding: var(--ks-space-2) var(--ks-space-3); border: 1px solid #fbbf24; border-radius: var(--ks-radius-sm); color: #fef3c7; }
|
||||
.ks-shell__nav { grid-area: nav; padding: var(--ks-space-4); border-right: 1px solid var(--ks-color-neutral-200); background: #fff; }
|
||||
.ks-shell__main { grid-area: main; min-width: 0; padding: var(--ks-space-6); }
|
||||
.ks-shell__footer { grid-area: footer; padding: var(--ks-space-2) var(--ks-space-6); border-top: 1px solid var(--ks-color-neutral-200); background: #fff; color: var(--ks-color-neutral-600); font-size: var(--ks-font-caption); }
|
||||
.ks-skip { position: fixed; left: var(--ks-space-2); top: -4rem; z-index: 1000; padding: var(--ks-space-2); background: #fff; } .ks-skip:focus { top: var(--ks-space-2); }
|
||||
@media (max-width: 900px) { .ks-shell { grid-template-columns: 1fr; grid-template-areas: 'header' 'nav' 'main' 'footer'; } .ks-shell__header { align-items: flex-start; flex-direction: column; } .ks-shell__nav { border-right: 0; border-bottom: 1px solid var(--ks-color-neutral-200); } }
|
||||
</style>
|
||||
@@ -0,0 +1,3 @@
|
||||
<script setup lang="ts">withDefaults(defineProps<{ asideWidth?: string; dense?: boolean }>(), { asideWidth: '24rem', dense: false })</script>
|
||||
<template><section class="ks-crud-workspace" :class="{ dense }" :style="{ '--ks-crud-aside': asideWidth }"><header v-if="$slots.toolbar"><slot name="toolbar" /></header><div class="ks-crud-workspace__body" :class="{ 'has-aside': $slots.aside }"><main><slot /></main><aside v-if="$slots.aside"><slot name="aside" /></aside></div><footer v-if="$slots.actions"><slot name="actions" /></footer></section></template>
|
||||
<style scoped>.ks-crud-workspace{display:grid;gap:var(--ks-space-3)}.ks-crud-workspace__body{display:grid;gap:var(--ks-space-4);min-width:0}.ks-crud-workspace__body.has-aside{grid-template-columns:minmax(0,1fr) var(--ks-crud-aside)}main,aside{min-width:0}.dense{gap:var(--ks-space-2)}@media(max-width:1100px){.ks-crud-workspace__body.has-aside{grid-template-columns:1fr}}</style>
|
||||
@@ -0,0 +1,2 @@
|
||||
<template><div class="ks-dashboard"><section class="ks-dashboard__kpis"><slot name="kpis" /></section><section class="ks-dashboard__primary ks-card"><slot name="primary" /></section><section class="ks-dashboard__secondary ks-card"><slot name="secondary" /></section><section class="ks-dashboard__alerts ks-card"><slot name="alerts" /></section></div></template>
|
||||
<style scoped>.ks-dashboard { display: grid; grid-template-columns: 2fr 1fr; gap: var(--ks-space-4); }.ks-dashboard__kpis { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); gap: var(--ks-space-3); }.ks-dashboard__primary,.ks-dashboard__secondary,.ks-dashboard__alerts { padding: var(--ks-space-4); }.ks-dashboard__alerts { grid-column: 1 / -1; }@media (max-width: 900px) { .ks-dashboard { grid-template-columns: 1fr; } }</style>
|
||||
@@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<div class="ks-form-layout">
|
||||
<form class="ks-form-layout__form ks-card" @submit.prevent="$emit('submit')"><slot /></form>
|
||||
<aside v-if="$slots.preview" class="ks-form-layout__preview ks-card"><slot name="preview" /></aside>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">defineEmits<{ submit: [] }>()</script>
|
||||
<style scoped>.ks-form-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(18rem, 26rem); gap: var(--ks-space-4); align-items: start; } .ks-form-layout__form,.ks-form-layout__preview { padding: var(--ks-space-4); } @media (max-width: 950px) { .ks-form-layout { grid-template-columns: 1fr; } }</style>
|
||||
@@ -0,0 +1,3 @@
|
||||
<script setup lang="ts">defineProps<{ title: string; runStatus?: string; watermark?: string; owner?: string }>()</script>
|
||||
<template><section class="ks-ops-console"><header><div><h1>{{ title }}</h1><p>상태 {{ runStatus ?? '-' }} · Watermark {{ watermark ?? '-' }} · Owner {{ owner ?? '-' }}</p></div><slot name="actions" /></header><div class="ks-ops-console__grid"><aside><slot name="runs" /></aside><main><slot /></main></div><footer v-if="$slots.footer"><slot name="footer" /></footer></section></template>
|
||||
<style scoped>.ks-ops-console{display:grid;gap:var(--ks-space-4)}header{display:flex;justify-content:space-between;gap:var(--ks-space-3)}h1{margin:0}.ks-ops-console__grid{display:grid;grid-template-columns:minmax(18rem,28rem) minmax(0,1fr);gap:var(--ks-space-4)}main,aside{min-width:0}@media(max-width:1000px){.ks-ops-console__grid{grid-template-columns:1fr}}</style>
|
||||
@@ -0,0 +1,31 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{ title: string; subtitle?: string; status?: string; asOf?: string; version?: string; asideWidth?: string }>()
|
||||
</script>
|
||||
<template>
|
||||
<section class="ks-page" :style="{ '--ks-aside-width': asideWidth ?? '22rem' }">
|
||||
<header class="ks-page__header">
|
||||
<div><h1>{{ title }}</h1><p v-if="subtitle">{{ subtitle }}</p><div class="ks-page__meta"><span v-if="status">상태: {{ status }}</span><span v-if="asOf">As-of: {{ asOf }}</span><span v-if="version">Version: {{ version }}</span></div></div>
|
||||
<div class="ks-page__actions"><slot name="actions" /></div>
|
||||
</header>
|
||||
<div v-if="$slots.summary" class="ks-page__summary"><slot name="summary" /></div>
|
||||
<div v-if="$slots.filters" class="ks-page__filters ks-card"><slot name="filters" /></div>
|
||||
<div class="ks-page__workspace" :class="{ 'has-aside': $slots.aside }">
|
||||
<div class="ks-page__content"><slot /></div>
|
||||
<aside v-if="$slots.aside" class="ks-page__aside"><slot name="aside" /></aside>
|
||||
</div>
|
||||
<footer v-if="$slots.footer" class="ks-page__footer"><slot name="footer" /></footer>
|
||||
</section>
|
||||
</template>
|
||||
<style scoped>
|
||||
.ks-page { max-width: var(--ks-content-max); margin: 0 auto; display: grid; gap: var(--ks-space-4); }
|
||||
.ks-page__header { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--ks-space-4); }
|
||||
h1 { margin: 0; font-size: var(--ks-font-page); line-height: var(--ks-line-page); } p { margin: var(--ks-space-1) 0 0; color: var(--ks-color-neutral-600); }
|
||||
.ks-page__meta { display: flex; gap: var(--ks-space-3); flex-wrap: wrap; margin-top: var(--ks-space-2); color: var(--ks-color-neutral-600); font-size: var(--ks-font-caption); }
|
||||
.ks-page__summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); gap: var(--ks-space-3); }
|
||||
.ks-page__filters { padding: var(--ks-space-3); }
|
||||
.ks-page__workspace { min-width: 0; display: grid; gap: var(--ks-space-4); }
|
||||
.ks-page__workspace.has-aside { grid-template-columns: minmax(0, 1fr) var(--ks-aside-width); }
|
||||
.ks-page__content, .ks-page__aside { min-width: 0; }
|
||||
.ks-page__footer { position: sticky; bottom: 0; z-index: 2; display: flex; justify-content: flex-end; gap: var(--ks-space-2); padding: var(--ks-space-3); border: 1px solid var(--ks-color-neutral-200); background: rgb(255 255 255 / 96%); }
|
||||
@media (max-width: 1100px) { .ks-page__workspace.has-aside { grid-template-columns: 1fr; } }
|
||||
</style>
|
||||
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<div class="ks-review-workbench">
|
||||
<section class="ks-review-workbench__queue ks-card" aria-label="검토 대기열"><slot name="queue" /></section>
|
||||
<section class="ks-review-workbench__detail ks-card" aria-label="결정 상세"><slot name="detail" /></section>
|
||||
<aside class="ks-review-workbench__decision ks-card" aria-label="검토 결정"><slot name="decision" /></aside>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.ks-review-workbench { display: grid; grid-template-columns: minmax(18rem, 28rem) minmax(24rem, 1fr) minmax(18rem, 24rem); gap: var(--ks-space-3); align-items: start; }
|
||||
.ks-review-workbench > * { min-height: 30rem; padding: var(--ks-space-4); }
|
||||
@media (max-width: 1200px) { .ks-review-workbench { grid-template-columns: 1fr; } }
|
||||
</style>
|
||||
@@ -0,0 +1,7 @@
|
||||
export { default as AppShellLayout } from './AppShellLayout.vue'
|
||||
export { default as PageLayout } from './PageLayout.vue'
|
||||
export { default as DashboardLayout } from './DashboardLayout.vue'
|
||||
export { default as FormPageLayout } from './FormPageLayout.vue'
|
||||
export { default as ReviewWorkbenchLayout } from './ReviewWorkbenchLayout.vue'
|
||||
export { default as CrudWorkspaceLayout } from './CrudWorkspaceLayout.vue'
|
||||
export { default as OperationsConsoleLayout } from './OperationsConsoleLayout.vue'
|
||||
Reference in New Issue
Block a user