feat(wbs-ux): add OMS/WMS/ERP quick transaction modals to SystemSettingsView
Validators (Pushes and Pull Requests) / UI & Storage Validation (push) Failing after 12s
Validators (Pushes and Pull Requests) / Database & Schema Validation (push) Successful in 12s
Validators (Pushes and Pull Requests) / Core Validators & Database Setup (push) Failing after 21s
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 11s
Validators (Pushes and Pull Requests) / CI Workflow Lint (push) Failing after 9s
Validators (Pushes and Pull Requests) / Notify PR Results (push) Has been skipped

This commit is contained in:
2026-07-25 20:33:48 +09:00
parent 82c619388c
commit 40251d2aaa
+151 -38
View File
@@ -39,8 +39,17 @@ const activeDomain = ref<'ALL' | 'OMS' | 'WMS' | 'ERP'>('ALL');
const searchKeyword = ref('');
const activeCategoryTab = ref('ALL');
// 2. 동적 드래그 반응형 Split Pane Resizer & 1-Click 스플릿 프리셋
const masterPanelWidth = ref(60); // 기본 60%
// 2. OMS / WMS / ERP 전용 퀵 트랜잭션 모달 상태
const isOmsModalOpen = ref(false);
const isWmsModalOpen = ref(false);
const isErpModalOpen = ref(false);
const omsOrderForm = ref({ symbol: '005930 (삼성전자)', orderType: 'LIMIT', price: '72,500', qty: '100' });
const wmsVaultForm = ref({ fromAccount: 'D+2 Vault Main', toAccount: 'KIS Trading Account', amount: '50,000,000' });
const erpApprovalForm = ref({ reqId: 'REQ-2026-0725', approver: 'risk_director_kjh', decision: 'APPROVED', comment: '리스크 가드 검토 승인 완료' });
// 3. 동적 드래그 반응형 Split Pane Resizer & 1-Click 스플릿 프리셋
const masterPanelWidth = ref(60);
const isDraggingSplitter = ref(false);
const setSplitRatio = (percent: number) => {
@@ -72,12 +81,12 @@ const stopSplitterDrag = () => {
document.removeEventListener('mouseup', stopSplitterDrag);
};
// 3. Master-Detail 바인딩 및 편집 모드 토글 상태
// 4. Master-Detail 바인딩 및 편집 모드 토글 상태
const items = ref<SettingItem[]>([]);
const selectedItem = ref<SettingItem | null>(null);
const isEditMode = ref(false);
// 4. 현장감 텔레메트리, 소켓, AI AX 코파일럿 상태
// 5. 현장감 텔레메트리, 소켓, AI AX 코파일럿 상태
const pingMs = ref(4);
const isBatchRunning = ref(false);
const batchProgress = ref(0);
@@ -91,12 +100,12 @@ const liveLogs = ref<string[]>([
'[14:02:15] [WARN] WMS Vault Safety Check: D+2 Cash level 500,000,000 KRW OK'
]);
// 5. 페이지네이션 및 드롭다운 상태
// 6. 페이지네이션 및 드롭다운 상태
const currentPage = ref(1);
const showExportMenu = ref(false);
const isGuideModalOpen = ref(false);
// 6. 토스트 알림 메시지
// 7. 토스트 알림 메시지
const toastMessage = ref<{ text: string; type: 'success' | 'warning' | 'error' } | null>(null);
const showToast = (text: string, type: 'success' | 'warning' | 'error' = 'success') => {
toastMessage.value = { text, type };
@@ -105,7 +114,7 @@ const showToast = (text: string, type: 'success' | 'warning' | 'error' = 'succes
}, 3000);
};
// 7. 모달 대화상자 상태
// 8. 모달 대화상자 상태
const isModalOpen = ref(false);
const modalItem = ref<SettingItem>({
id: 0,
@@ -120,7 +129,7 @@ const modalItem = ref<SettingItem>({
maker_checker: 'APPROVED'
});
// 8. 필터링된 항목 계산
// 9. 필터링된 항목 계산
const filteredItems = computed(() => {
return items.value.filter(item => {
const matchDomain = activeDomain.value === 'ALL' || item.domain === activeDomain.value;
@@ -132,7 +141,7 @@ const filteredItems = computed(() => {
});
});
// 9. AG Grid 컬럼 정의
// 10. AG Grid 컬럼 정의
const columnDefs = ref<ColDef[]>([
{ field: 'id', headerName: 'ID', width: 55, sortable: true },
{ field: 'domain', headerName: '도메인', width: 85, cellRenderer: (p: any) => `<span class="domain-tag ${p.value.toLowerCase()}">${p.value}</span>` },
@@ -200,6 +209,24 @@ const runFactorBatch = () => {
}, 300);
};
const submitOmsOrder = () => {
isOmsModalOpen.value = false;
liveLogs.value.unshift(`[${new Date().toLocaleTimeString()}] [OMS] Submitted Order: ${omsOrderForm.value.symbol} ${omsOrderForm.value.qty}개 (${omsOrderForm.value.price}원)`);
showToast(`📈 OMS 주문이 성공적으로 전송되었습니다 (${omsOrderForm.value.symbol}).`, 'success');
};
const executeWmsTransfer = () => {
isWmsModalOpen.value = false;
liveLogs.value.unshift(`[${new Date().toLocaleTimeString()}] [WMS] Transferred ${wmsVaultForm.value.amount} KRW from ${wmsVaultForm.value.fromAccount}`);
showToast(`🏦 WMS 현금 이체가 완료되었습니다 (${wmsVaultForm.value.amount} KRW).`, 'success');
};
const approveErpRequest = () => {
isErpModalOpen.value = false;
liveLogs.value.unshift(`[${new Date().toLocaleTimeString()}] [ERP] Request ${erpApprovalForm.value.reqId} approved by ${erpApprovalForm.value.approver}`);
showToast(`📑 ERP Maker-Checker 결재 승인이 완료되었습니다.`, 'success');
};
const applyAiRecommendation = () => {
if (selectedItem.value) {
selectedItem.value.setting_value = '68.5';
@@ -299,12 +326,19 @@ onMounted(loadData);
<span class="db-ping-chip">🟢 Live ({{ pingMs }}ms)</span>
<span class="socket-chip">📡 SignalR Active</span>
</div>
<!-- OMS / WMS / ERP 3 도메인 스위처 -->
<!-- OMS / WMS / ERP 3 도메인 스위처 & Quick Modals Trigger -->
<div class="domain-switcher-bar">
<button class="domain-btn" :class="{ active: activeDomain === 'ALL' }" @click="activeDomain = 'ALL'">🌐 전체 도메인</button>
<button class="domain-btn" :class="{ active: activeDomain === 'OMS' }" @click="activeDomain = 'OMS'">📈 OMS (주문/체결)</button>
<button class="domain-btn" :class="{ active: activeDomain === 'WMS' }" @click="activeDomain = 'WMS'">🏦 WMS (자산/현금)</button>
<button class="domain-btn" :class="{ active: activeDomain === 'ERP' }" @click="activeDomain = 'ERP'">📑 ERP (재무/회계)</button>
<button class="domain-btn" :class="{ active: activeDomain === 'ALL' }" @click="activeDomain = 'ALL'">🌐 전체</button>
<button class="domain-btn" :class="{ active: activeDomain === 'OMS' }" @click="activeDomain = 'OMS'">📈 OMS (주문)</button>
<button class="domain-btn" :class="{ active: activeDomain === 'WMS' }" @click="activeDomain = 'WMS'">🏦 WMS (자산)</button>
<button class="domain-btn" :class="{ active: activeDomain === 'ERP' }" @click="activeDomain = 'ERP'">📑 ERP (재무)</button>
<!-- 3대 도메인 트랜잭션 모달 버튼 -->
<div class="quick-modal-triggers">
<button class="btn-quick-domain oms" @click="isOmsModalOpen = true">+ OMS 주문전송</button>
<button class="btn-quick-domain wms" @click="isWmsModalOpen = true">+ WMS 현금이체</button>
<button class="btn-quick-domain erp" @click="isErpModalOpen = true">+ ERP 결재승인</button>
</div>
</div>
</div>
@@ -313,7 +347,7 @@ onMounted(loadData);
<button class="btn-batch-trigger" @click="runFactorBatch" :disabled="isBatchRunning">
{{ isBatchRunning ? `⏳ 배치 ${batchProgress}%` : '⚡ 팩터 배치 실행' }}
</button>
<button class="btn-guide-spec" @click="isGuideModalOpen = true">💡 20 명세 팝업</button>
<button class="btn-guide-spec" @click="isGuideModalOpen = true">💡 22 명세 팝업</button>
<div class="search-box">
<input type="text" class="search-input" placeholder="설정 키/설명 검색..." v-model="searchKeyword" />
</div>
@@ -354,7 +388,6 @@ onMounted(loadData);
</button>
</div>
<!-- 1-Click 스플릿 비율 프리셋 -->
<div class="right-split-presets">
<span class="preset-label"> 스플릿 비율:</span>
<button class="preset-btn" :class="{ active: masterPanelWidth === 30 }" @click="setSplitRatio(30)">3:7</button>
@@ -529,6 +562,63 @@ onMounted(loadData);
<span class="telemetry-item"> Hangfire Jobs: <strong>Healthy</strong></span>
</div>
<!-- OMS Quick Order Modal -->
<div class="modal-backdrop" v-if="isOmsModalOpen">
<div class="modal-dialog">
<div class="modal-header">
<h4 class="modal-title">📈 OMS 주문 전송 트랜잭션 Modal</h4>
<button class="btn-close-modal" @click="isOmsModalOpen = false"></button>
</div>
<div class="modal-body">
<div class="form-row mb-2"><QuantLabel text="종목 명칭/코드" /><QuantInput v-model="omsOrderForm.symbol" /></div>
<div class="form-row mb-2"><QuantLabel text="주문 단가 (KRW)" /><QuantInput v-model="omsOrderForm.price" /></div>
<div class="form-row mb-2"><QuantLabel text="주문 수량 (주)" /><QuantInput v-model="omsOrderForm.qty" /></div>
</div>
<div class="modal-footer">
<button class="btn-modal-cancel" @click="isOmsModalOpen = false">취소</button>
<button class="btn-modal-save" @click="submitOmsOrder">주문 전송 실행</button>
</div>
</div>
</div>
<!-- WMS Quick Vault Transfer Modal -->
<div class="modal-backdrop" v-if="isWmsModalOpen">
<div class="modal-dialog">
<div class="modal-header">
<h4 class="modal-title">🏦 WMS 자산/현금 이체 Vault Modal</h4>
<button class="btn-close-modal" @click="isWmsModalOpen = false"></button>
</div>
<div class="modal-body">
<div class="form-row mb-2"><QuantLabel text="출금 계좌" /><QuantInput v-model="wmsVaultForm.fromAccount" /></div>
<div class="form-row mb-2"><QuantLabel text="입금 계좌" /><QuantInput v-model="wmsVaultForm.toAccount" /></div>
<div class="form-row mb-2"><QuantLabel text="이체 금액 (KRW)" /><QuantInput v-model="wmsVaultForm.amount" /></div>
</div>
<div class="modal-footer">
<button class="btn-modal-cancel" @click="isWmsModalOpen = false">취소</button>
<button class="btn-modal-save" @click="executeWmsTransfer">이체 실행</button>
</div>
</div>
</div>
<!-- ERP Quick Maker-Checker Modal -->
<div class="modal-backdrop" v-if="isErpModalOpen">
<div class="modal-dialog">
<div class="modal-header">
<h4 class="modal-title">📑 ERP Maker-Checker 결재 승인 Modal</h4>
<button class="btn-close-modal" @click="isErpModalOpen = false"></button>
</div>
<div class="modal-body">
<div class="form-row mb-2"><QuantLabel text="결재 요청 ID" /><QuantInput v-model="erpApprovalForm.reqId" readonly /></div>
<div class="form-row mb-2"><QuantLabel text="승인자 ID" /><QuantInput v-model="erpApprovalForm.approver" readonly /></div>
<div class="form-row mb-2"><QuantLabel text="검토 의견" /><QuantTextArea v-model="erpApprovalForm.comment" :rows="2" /></div>
</div>
<div class="modal-footer">
<button class="btn-modal-cancel" @click="isErpModalOpen = false">취소</button>
<button class="btn-modal-save" @click="approveErpRequest">최종 결재 승인</button>
</div>
</div>
</div>
<!-- Modal Dialog (신규 등록 대화상자) -->
<div class="modal-backdrop" v-if="isModalOpen">
<div class="modal-dialog">
@@ -565,35 +655,37 @@ onMounted(loadData);
</div>
</div>
<!-- 20 OMS/WMS/ERP/AX & 스플릿 명세 가이드 Modal -->
<!-- 22 OMS/WMS/ERP/AX & 스플릿 명세 가이드 Modal -->
<div class="modal-backdrop" v-if="isGuideModalOpen">
<div class="modal-dialog guide-modal">
<div class="modal-header">
<h4 class="modal-title">💡 OMS / WMS / ERP / AX & 동적 스플릿 20 컴포넌트 스펙</h4>
<h4 class="modal-title">💡 OMS / WMS / ERP / AX & 스플릿 22 컴포넌트 스펙</h4>
<button class="btn-close-modal" @click="isGuideModalOpen = false"></button>
</div>
<div class="modal-body guide-body">
<ul class="guide-list">
<li><strong>1. OMS 도메인 </strong>: 주문/체결 Waterfall 우선순위 & 호가 스프레드 뷰er</li>
<li><strong>2. WMS 도메인 </strong>: D+2 현금 볼트 안전율 & 포지션 사이징 가드</li>
<li><strong>3. ERP 도메 모듈</strong>: 재무 회계 계정 맵핑 & Maker-Checker 승인 릴레이</li>
<li><strong>4. AI AX 코파일럿 배너</strong>: Antigravity AI 추천값 1-Click 자동 적용</li>
<li><strong>5. 물리적 동적 스플릿 (Draggable Resizer)</strong>: 마우스 드래그 20%~80% 분할 조절</li>
<li><strong>6. 1-Click 스플릿 프리셋 </strong>: 3:7 / 5:5 / 6:4 / 7:3 분할 조절 버튼</li>
<li><strong>7. Live PostgreSQL Ping 레이턴시 </strong>: 4ms 실시간 상태</li>
<li><strong>8. SignalR WebSocket 소켓 </strong>: 라이브 소켓 연결 지표</li>
<li><strong>9. DbUp 마이그레이션 태그</strong>: DB 마이그레이션 태그 v2026.07.25</li>
<li><strong>10. 실시간 파이프라인 로그 터미널 </strong>: 엔진 트랜잭션 스트리밍</li>
<li><strong>11. 비동기 배치 실행 & 진행률 </strong>: 0~100% 모의 트랜잭션 게이지</li>
<li><strong>12. 낙관적 버전 인디케이터</strong>: 동시성 충돌 방지 v1~v5</li>
<li><strong>13. 실시간 텔레메트리 </strong>: CPU/RAM/DB Pool 현장감 지표</li>
<li><strong>14. 검색 & 핫키 </strong>: F3/F4/F5/F7 더존 표준 핫키</li>
<li><strong>15. 카테고리 </strong>: ALL/BUDGET/FACTOR/RISK/ACCOUNTING </li>
<li><strong>16. AG Grid 데이터 테이블</strong>: 정렬, 필터, 단일 선택, Status Chips</li>
<li><strong>17. 페이지네이션 </strong>: Page 1 of 1 건수 페이지 컨트롤러</li>
<li><strong>18. 더존 6 표준 입력 마스크</strong>: Input, ComboBox, Radio, TextArea </li>
<li><strong>19. 읽기/편집 모드 토글</strong>: 👁 읽기 / 편집 전환 스위치</li>
<li><strong>20. 감사 이력 타임라인 & 모달 & 엑셀 팝업</strong>: Audit Trail, Modal, Excel/CSV</li>
<li><strong>1. OMS 주문전송 팝업 </strong>: 종목/단가/수량 매수주문 팝업</li>
<li><strong>2. WMS 현금이체 팝업 </strong>: D+2 Vault 현금 출금이체 팝업</li>
<li><strong>3. ERP 결재승 팝업 모달</strong>: Maker-Checker 최종 승인 팝업</li>
<li><strong>4. OMS 도메인 모듈</strong>: 주문/체결 Waterfall 우선순위 & 호가 뷰er</li>
<li><strong>5. WMS 도메인 모듈</strong>: D+2 현금 볼트 안전율 & 포지션 사이징 가드</li>
<li><strong>6. ERP 도메인 모듈</strong>: 재무 회계 계정 맵핑 & Maker-Checker 릴레이</li>
<li><strong>7. AI AX 코파일럿 배너</strong>: Antigravity AI 추천값 1-Click 자동 적용</li>
<li><strong>8. 물리적 동적 스플릿 (Draggable Resizer)</strong>: 마우스 드래그 분할 조절</li>
<li><strong>9. 1-Click 스플릿 프리셋 </strong>: 3:7 / 5:5 / 6:4 / 7:3 분할 조절 버튼</li>
<li><strong>10. Live PostgreSQL Ping 레이턴시 </strong>: 4ms 실시간 상태</li>
<li><strong>11. SignalR WebSocket 소켓 </strong>: 라이브 소켓 연결 지표</li>
<li><strong>12. DbUp 마이그레이션 태그</strong>: DB 마이그레이션 태그 v2026.07.25</li>
<li><strong>13. 실시간 파이프라인 로그 터미널 </strong>: 엔진 트랜잭션 스트리밍</li>
<li><strong>14. 비동기 배치 실행 & 진행률 </strong>: 0~100% 모의 트랜잭션 게이지</li>
<li><strong>15. 낙관적 버전 인디케이터</strong>: 동시성 충돌 방지 v1~v5</li>
<li><strong>16. 실시간 텔레메트리 </strong>: CPU/RAM/DB Pool 현장감 지표</li>
<li><strong>17. 검색 & 핫키 </strong>: F3/F4/F5/F7 더존 표준 핫키</li>
<li><strong>18. 카테고리 </strong>: ALL/BUDGET/FACTOR/RISK/ACCOUNTING </li>
<li><strong>19. AG Grid 데이터 테이블</strong>: 정렬, 필터, 단일 선택, Status Chips</li>
<li><strong>20. 페이지네이션 </strong>: Page 1 of 1 건수 페이지 컨트롤러</li>
<li><strong>21. 더존 6 표준 입력 마스크</strong>: Input, ComboBox, Radio, TextArea </li>
<li><strong>22. 읽기/편집 모드 토글 & 감사 이력 & 엑셀 팝업</strong>: Audit Trail, Excel/CSV</li>
</ul>
</div>
<div class="modal-footer">
@@ -617,6 +709,26 @@ onMounted(loadData);
user-select: none;
}
.quick-modal-triggers {
display: flex;
gap: 4px;
margin-left: 12px;
}
.btn-quick-domain {
font-size: 0.65rem;
font-weight: 700;
padding: 2px 6px;
border: none;
border-radius: 3px;
color: white;
cursor: pointer;
}
.btn-quick-domain.oms { background: #2563EB; }
.btn-quick-domain.wms { background: #166534; }
.btn-quick-domain.erp { background: #6B46C1; }
.category-tabs-bar {
display: flex;
justify-content: space-between;
@@ -657,6 +769,7 @@ onMounted(loadData);
.domain-switcher-bar {
display: flex;
align-items: center;
gap: 4px;
margin-top: 4px;
}