lexistudio / templates /toss_dark.html
scipious's picture
Upload 16 files
c514a40 verified
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>트리니티2 - 자동차 인증 법규를 더 쉽게</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.socket.io/4.7.2/socket.io.min.js"></script>
<style>
/* ... existing styles ... */
:root {
--primary-color: #4da8ff;
--primary-hover: #4d8cff;
--bg-primary: #1a1a1a;
--bg-secondary: #2c2c2c;
--bg-tertiary: #333;
--bg-quaternary: #444;
--text-primary: #e0e0e0;
--text-secondary: #b0b0b0;
--text-muted: #888;
--border-color: #444;
--shadow: 0 2px 8px rgba(0,0,0,0.2);
--radius: 8px;
--success-color: #4caf50;
--warning-color: #ff9800;
}
* {
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Noto Sans KR', sans-serif;
margin: 0;
padding: 0;
background-color: var(--bg-primary);
color: var(--text-primary);
line-height: 1.6;
}
/* ===== 헤더 ===== */
.header {
background: var(--bg-secondary);
padding: 16px 24px;
box-shadow: var(--shadow);
display: flex;
justify-content: space-between;
align-items: center;
position: sticky;
top: 0;
z-index: 100;
}
.logo {
font-size: 28px;
font-weight: 700;
color: var(--primary-color);
letter-spacing: -0.5px;
}
.nav {
display: flex;
list-style: none;
gap: 32px;
margin: 0;
padding: 0;
}
.nav a {
text-decoration: none;
color: var(--text-secondary);
font-weight: 500;
padding: 8px 12px;
border-radius: var(--radius);
transition: all 0.2s ease;
}
.nav a:hover {
color: var(--primary-hover);
background: rgba(77, 168, 255, 0.1);
}
/* ===== 메인 컨텐츠 ===== */
.main {
max-width: 1200px;
margin: 0 auto;
padding: 32px 24px;
}
.hero {
text-align: center;
margin-bottom: 48px;
}
.hero-title {
font-size: 42px;
font-weight: 700;
color: var(--text-primary);
margin-bottom: 12px;
letter-spacing: -1px;
}
.hero-subtitle {
font-size: 20px;
color: var(--text-secondary);
margin: 0 0 24px 0;
}
.status-text {
padding: 12px 20px;
background: var(--bg-tertiary);
border-radius: var(--radius);
display: inline-block;
font-size: 14px;
color: var(--primary-color);
}
/* ===== 검색 섹션 ===== */
.search-section {
background: var(--bg-secondary);
border-radius: 16px;
padding: 32px;
box-shadow: var(--shadow);
margin-bottom: 32px;
}
.section-title {
font-size: 24px;
font-weight: 600;
margin-bottom: 24px;
color: var(--text-primary);
}
.checkbox-container {
display: flex;
gap: 24px;
flex-wrap: wrap;
margin-bottom: 24px;
align-items: center;
padding: 16px;
background: var(--bg-tertiary);
border-radius: var(--radius);
}
.checkbox-label {
display: flex;
align-items: center;
gap: 8px;
font-size: 14px;
color: var(--text-secondary);
cursor: pointer;
transition: color 0.2s ease;
}
.checkbox-label:hover {
color: var(--text-primary);
}
.checkbox-label input[type="checkbox"] {
accent-color: var(--primary-color);
transform: scale(1.1);
}
.search-controls {
display: flex;
gap: 12px;
margin-bottom: 24px;
flex-wrap: wrap;
}
.search-input {
padding: 12px 16px;
border: 2px solid var(--border-color);
border-radius: var(--radius);
font-size: 16px;
flex: 1;
min-width: 300px;
background: var(--bg-tertiary);
color: var(--text-primary);
transition: border-color 0.2s ease;
}
.search-input:focus {
outline: none;
border-color: var(--primary-color);
}
.search-input::placeholder {
color: var(--text-muted);
}
.btn {
padding: 12px 20px;
border: none;
border-radius: var(--radius);
background: var(--primary-color);
color: white;
cursor: pointer;
font-size: 14px;
font-weight: 600;
transition: all 0.2s ease;
white-space: nowrap;
}
.btn:hover {
background: var(--primary-hover);
transform: translateY(-1px);
}
.btn-secondary {
background: var(--bg-quaternary);
}
.btn-secondary:hover {
background: #555;
}
/* ===== 결과 컨테이너 ===== */
.results-container {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 24px;
margin-top: 24px;
}
.result-panel {
padding: 24px;
border-radius: 12px;
min-height: 200px;
box-shadow: var(--shadow);
}
.regulation-list {
background: var(--bg-tertiary);
}
.search-results {
background: var(--bg-quaternary);
}
.panel-title {
font-size: 18px;
font-weight: 600;
margin-bottom: 16px;
color: var(--text-primary);
border-bottom: 2px solid var(--primary-color);
padding-bottom: 8px;
display: flex;
justify-content: space-between;
align-items: center;
}
.selected-count {
font-size: 14px;
color: var(--primary-color);
background: rgba(77, 168, 255, 0.1);
padding: 4px 8px;
border-radius: 4px;
}
.regulation-item {
padding: 12px;
margin: 8px 0;
background: var(--bg-quaternary);
border-radius: var(--radius);
cursor: pointer;
transition: all 0.2s ease;
border: 2px solid transparent;
user-select: none;
}
.regulation-item:hover {
background: #3a3a3a;
border-color: var(--primary-color);
}
.regulation-item.selected {
background: var(--primary-color);
color: white;
border-color: var(--primary-hover);
}
.regulation-item.selected:hover {
background: var(--primary-hover);
}
.region-table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
margin-bottom: 16px;
border-radius: var(--radius);
overflow: hidden;
box-shadow: var(--shadow);
}
.region-table th,
.region-table td {
padding: 12px 16px;
border: 1px solid var(--border-color);
text-align: left;
background: var(--bg-secondary);
}
.region-table th {
background: var(--bg-quaternary);
font-weight: 600;
text-align: center;
color: var(--primary-color);
}
.action-buttons {
display: flex;
gap: 12px;
margin-top: 16px;
padding-top: 16px;
border-top: 1px solid var(--border-color);
}
.btn-submit {
background: var(--success-color);
}
.btn-submit:hover {
background: #45a049;
}
.btn-clear {
background: var(--warning-color);
}
.btn-clear:hover {
background: #f57c00;
}
/* ===== 푸터 ===== */
.footer {
text-align: center;
padding: 48px 24px;
color: var(--text-secondary);
border-top: 1px solid var(--border-color);
margin-top: 48px;
}
/* ===== 반응형 ===== */
@media (max-width: 768px) {
.header {
padding: 12px 16px;
}
.nav {
gap: 16px;
}
.hero-title {
font-size: 28px;
}
.main {
padding: 16px;
}
.search-section {
padding: 20px;
}
.results-container {
grid-template-columns: 1fr;
}
.search-controls {
flex-direction: column;
}
.search-input {
min-width: auto;
}
.checkbox-container {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.action-buttons {
flex-direction: column;
}
.search-results-content {
white-space: pre-wrap;
word-wrap: break-word;
line-height: 1.6;
}
}
@media (max-width: 480px) {
.checkbox-container {
padding: 12px;
}
.nav {
display: none;
}
}
</style>
</head>
<body>
<header class="header">
<div class="logo">트리니티</div>
<nav>
<ul class="nav">
<li><a href="#">법규 검색</a></li>
<li><a href="#">체크리스트 생성</a></li>
<li><a href="#">유권해석</a></li>
<li><a href="#">사용문의</a></li>
</ul>
</nav>
</header>
<main class="main">
<section class="hero">
<h1 class="hero-title">자동차 인증 법규를 더 쉽게</h1>
<p class="hero-subtitle">관련 법규를 검색으로 편리하게 찾아보세요</p>
<div id="statusText" class="status-text">시스템 준비 중...</div>
</section>
<section class="search-section">
<h2 class="section-title">법규 검색</h2>
<div class="checkbox-container">
<span class="checkbox-label"><strong>검색 범위:</strong></span>
<label class="checkbox-label">
<input type="checkbox" id="allRegions">
모두 선택
</label>
<label class="checkbox-label">
<input type="checkbox" class="region-checkbox" value="국내">
국내
</label>
<label class="checkbox-label">
<input type="checkbox" class="region-checkbox" value="북미">
북미
</label>
<label class="checkbox-label">
<input type="checkbox" class="region-checkbox" value="유럽">
유럽
</label>
</div>
<div class="search-controls">
<input
type="text"
id="searchInput"
class="search-input"
placeholder="검색하고 싶은 내용을 입력하세요 (예: ISA 기능과 관련된 법규가 뭐야?)"
>
<button class="btn" onclick="showMessage()">검색</button>
<button class="btn btn-secondary" onclick="loadRegulationList()">법규 리스트</button>
</div>
<div class="results-container">
<div class="result-panel regulation-list">
<div class="panel-title">
법규 리스트
<span id="selectedCount" class="selected-count">선택됨: 0</span>
</div>
<div id="regulationList">
<div class="regulation-item" data-id="reg1" data-title="국내 배출가스 기준">
법규 1 - 국내 배출가스 기준
</div>
<div class="regulation-item" data-id="reg2" data-title="북미 안전 기준">
법규 2 - 북미 안전 기준
</div>
<div class="regulation-item" data-id="reg3" data-title="유럽 환경 규정">
법규 3 - 유럽 환경 규정
</div>
</div>
<div class="action-buttons">
<button class="btn btn-submit" onclick="submitSelectedRegulations()">선택 항목 전송</button>
<button class="btn btn-clear" onclick="clearAllSelections()">선택 초기화</button>
</div>
</div>
<div class="result-panel search-results">
<div class="panel-title">검색 결과</div>
<div id="searchResults">검색 결과가 여기에 표시됩니다.</div>
</div>
</div>
</section>
</main>
<footer class="footer">
<p>© 2024 법규인증3팀 - 트리니티 시스템</p>
</footer>
<script>
// ===== 전역 변수 =====
let selectedRegulations = [];
let socket;
// ===== 초기화 =====
document.addEventListener('DOMContentLoaded', function() {
initializeSocket();
initializeEventListeners();
updateSelectedCount();
});
// ===== Socket.IO 초기화 =====
function initializeSocket() {
socket = io();
socket.on('message', function(data) {
document.getElementById('statusText').innerText = data.message;
});
}
// ===== 이벤트 리스너 초기화 =====
function initializeEventListeners() {
// 전체 선택 체크박스
document.getElementById('allRegions').addEventListener('change', toggleAllRegions);
// 개별 체크박스들에 이벤트 리스너 추가
document.querySelectorAll('.region-checkbox').forEach(checkbox => {
checkbox.addEventListener('change', updateAllRegionsCheckbox);
});
// 검색 입력 엔터키
document.getElementById('searchInput').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
showMessage();
}
});
// 법규 리스트 이벤트 위임 (동적으로 추가되는 항목들도 클릭 가능)
document.getElementById('regulationList').addEventListener('click', function(e) {
const item = e.target.closest('.regulation-item');
if (item) {
toggleSelection(item);
}
});
}
// ===== 지역 선택 관련 함수 =====
function toggleAllRegions() {
const allCheckbox = document.getElementById('allRegions');
const regionCheckboxes = document.querySelectorAll('.region-checkbox');
regionCheckboxes.forEach(checkbox => {
checkbox.checked = allCheckbox.checked;
});
}
// 개별 체크박스 변경 시 "모두 선택" 체크박스 상태 업데이트
function updateAllRegionsCheckbox() {
const allCheckbox = document.getElementById('allRegions');
const regionCheckboxes = document.querySelectorAll('.region-checkbox');
const checkedCount = document.querySelectorAll('.region-checkbox:checked').length;
if (checkedCount === 0) {
// 아무것도 선택되지 않음
allCheckbox.checked = false;
allCheckbox.indeterminate = false;
} else if (checkedCount === regionCheckboxes.length) {
// 모두 선택됨
allCheckbox.checked = true;
allCheckbox.indeterminate = false;
} else {
// 일부만 선택됨
allCheckbox.checked = false;
allCheckbox.indeterminate = true;
}
}
function getSelectedRegions() {
const checkboxes = document.querySelectorAll('.region-checkbox:checked');
return Array.from(checkboxes).map(cb => cb.value);
}
// ===== 검색 관련 함수 (기존 performSearch를 showMessage로 통합) =====
function showMessage() {
const query = document.getElementById('searchInput').value.trim();
const resultsDiv = document.getElementById('searchResults');
const selectedRegions = getSelectedRegions();
if (!query) {
resultsDiv.innerHTML = '<p style="color: var(--text-muted);">검색어를 입력해주세요.</p>';
return;
}
// 로딩 상태 표시
resultsDiv.innerHTML = '<p>검색 중...</p>';
// 검색과 선택된 법규 정보를 함께 서버에 전송
const requestData = {
query: query,
regions: selectedRegions,
selectedRegulations: selectedRegulations.map(id => {
const element = document.querySelector(`[data-id="${id}"]`);
return {
id: id,
title: element ? element.getAttribute('data-title') || element.textContent.trim() : id
};
})
};
fetch('/get_message', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(requestData)
})
.then(response => response.json())
.then(data => {
displaySearchResults(data, query, selectedRegions);
})
.catch(error => {
console.error('검색 오류:', error);
resultsDiv.innerHTML = '<p style="color: #ff6b6b;">검색 중 오류가 발생했습니다.</p>';
});
}
function displaySearchResults(data, query, selectedRegions) {
const resultsDiv = document.getElementById('searchResults');
if (selectedRegions.length === 0) {
selectedRegions = ['국내', '북미', '유럽'];
}
let resultsHTML = `
<div style="margin-bottom: 16px; padding: 12px; background: var(--bg-tertiary); border-radius: var(--radius);">
<p><strong>검색어:</strong> ${query}</p>
${selectedRegulations.length > 0 ? `<p><strong>선택된 법규:</strong> ${selectedRegulations.length}개</p>` : ''}
</div>
`;
if (data.message) {
resultsHTML += `<div class="search-results-content" style="margin: 16px 0; padding: 16px; background: var(--bg-tertiary); border-radius: var(--radius);">
${data.message}
</div>`;
}
selectedRegions.forEach(region => {
const content = `${region} 관련 규정: ${query}에 대한 내용`;
const regId = `REG-${Math.random().toString(36).substr(2, 9).toUpperCase()}`;
const updateDate = new Date().toLocaleDateString('ko-KR');
resultsHTML += `
<table class="region-table">
<tr>
<th>${region}</th>
<td>
<ul style="margin: 0; padding-left: 20px;">
<li>법규 ID: ${regId}</li>
<li>내용: ${content}</li>
<li>업데이트: ${updateDate}</li>
</ul>
</td>
</tr>
</table>
`;
});
resultsDiv.innerHTML = resultsHTML;
}
// ===== 법규 리스트 관련 함수 =====
function loadRegulationList() {
const selectedRegions = getSelectedRegions();
const listDiv = document.getElementById('regulationList');
listDiv.innerHTML = '<p>법규 리스트 로딩 중...</p>';
fetch('/get_reg_list', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ regions: selectedRegions })
})
.then(response => response.json())
.then(data => {
if (data.reg_list_part) {
displayRegulationList(data.reg_list_part);
} else {
listDiv.innerHTML = '<p style="color: var(--text-muted);">법규 리스트를 불러올 수 없습니다.</p>';
}
//if (data.reg_list_section) {
// displayRegulationList(data.reg_list_section);
//} else {
// listDiv.innerHTML = '<p style="color: var(--text-muted);">법규 리스트를 불러올 수 없습니다.</p>';
//}
})
.catch(error => {
console.error('법규 리스트 로딩 오류:', error);
listDiv.innerHTML = '<p style="color: #ff6b6b;">법규 리스트 로딩 중 오류가 발생했습니다.</p>';
});
}
function displayRegulationList(data) {
const listDiv = document.getElementById('regulationList');
// 서버 데이터를 파싱해서 클릭 가능한 항목들로 변환
// 실제 데이터 구조에 맞게 수정 필요
let listHTML = '';
if (typeof data === 'string') {
// 문자열 데이터를 줄 단위로 분할해서 처리
const lines = data.split('\n').filter(line => line.trim());
lines.forEach((line, index) => {
const regId = `reg_${Date.now()}_${index}`;
const isSelected = selectedRegulations.includes(regId);
listHTML += `
<div class="regulation-item ${isSelected ? 'selected' : ''}"
data-id="${regId}"
data-title="${line.trim()}">
${line.trim()}
</div>
`;
});
} else if (Array.isArray(data)) {
// 배열 데이터 처리
data.forEach((item, index) => {
const regId = item.id || `reg_${Date.now()}_${index}`;
const title = item.title || item.name || item.toString();
const isSelected = selectedRegulations.includes(regId);
listHTML += `
<div class="regulation-item ${isSelected ? 'selected' : ''}"
data-id="${regId}"
data-title="${title}">
${title}
</div>
`;
});
} else {
// 기본 처리
listHTML = '<p style="color: var(--text-muted);">법규 데이터를 표시할 수 없습니다.</p>';
}
listDiv.innerHTML = listHTML;
updateSelectedCount();
}
// ===== 법규 선택 관련 함수 =====
function toggleSelection(element) {
const id = element.getAttribute('data-id');
if (selectedRegulations.includes(id)) {
selectedRegulations = selectedRegulations.filter(item => item !== id);
element.classList.remove('selected');
} else {
selectedRegulations.push(id);
element.classList.add('selected');
}
updateSelectedCount();
console.log('선택된 법규:', selectedRegulations);
}
function updateSelectedCount() {
const countElement = document.getElementById('selectedCount');
countElement.textContent = `선택됨: ${selectedRegulations.length}`;
}
function clearAllSelections() {
selectedRegulations = [];
document.querySelectorAll('.regulation-item').forEach(item => {
item.classList.remove('selected');
});
updateSelectedCount();
}
// ===== 데이터 전송 함수 =====
function submitSelectedRegulations() {
if (selectedRegulations.length === 0) {
alert('선택된 법규가 없습니다.');
return;
}
const messageData = {
selected: selectedRegulations.map(id => {
const element = document.querySelector(`[data-id="${id}"]`);
return {
id: id,
title: element ? element.getAttribute('data-title') || element.textContent.trim() : id
};
})
};
fetch('/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(messageData)
})
.then(response => {
if (response.ok) {
alert(`선택된 ${selectedRegulations.length}개 법규가 전송되었습니다!`);
} else {
alert('전송 실패');
}
})
.catch(error => {
console.error('전송 오류:', error);
alert('전송 중 오류가 발생했습니다.');
});
}
</script>
</body>
</html>