티스토리 뷰

검색 결과 바로 선택 기능이 추가된 통합 코드.html
0.01MB

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>HR 조직도 관리 시스템 - 검색 리스트 선택 기능</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <style>
        body { font-family: 'Pretendard', sans-serif; margin: 0; display: flex; height: 100vh; background: #f4f7f6; }
        
        /* [좌측 사이드바] */
        .sidebar { width: 400px; background: #fff; border-right: 1px solid #e0e0e0; padding: 25px; overflow-y: auto; display: flex; flex-direction: column; position: relative; }
        .detail-view { flex: 1; padding: 50px; background: #fff; display: flex; flex-direction: column; }

        /* [검색 영역] */
        .search-container { position: relative; display: flex; gap: 6px; margin-bottom: 20px; }
        .search-container input { flex: 1; padding: 12px; border: 1px solid #ddd; border-radius: 8px; outline: none; }
        
        /* 🚩 검색 결과 퀵 리스트 스타일 */
        #search-results-list { 
            position: absolute; top: 50px; left: 0; width: calc(100% - 100px); 
            background: white; border: 1px solid #007bff; border-radius: 8px; 
            z-index: 100; display: none; box-shadow: 0 10px 20px rgba(0,0,0,0.1);
            max-height: 200px; overflow-y: auto;
        }
        .result-item { padding: 10px 15px; cursor: pointer; border-bottom: 1px solid #eee; font-size: 14px; }
        .result-item:last-child { border-bottom: none; }
        .result-item:hover { background: #f0f7ff; color: #007bff; }
        .result-item .dept-name { font-size: 11px; color: #999; margin-left: 10px; }

        /* [버튼 스타일] */
        .btn { padding: 8px 16px; border: none; border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 13px; }
        .btn-search { background: #007bff; color: white; }
        .btn-reset { background: #6c757d; color: white; }
        .control-btns { display: flex; gap: 10px; margin-bottom: 15px; justify-content: flex-end; }
        .btn-text { background: none; border: none; color: #007bff; cursor: pointer; font-size: 12px; text-decoration: underline; }

        /* [트리 메뉴 스타일] */
        ul.tree, ul.tree ul { list-style: none; padding-left: 20px; margin: 0; }
        .tree li { margin: 8px 0; }
        .dept, .user { padding: 8px 12px; cursor: pointer; border-radius: 6px; display: inline-block; font-size: 14px; }
        .dept { font-weight: bold; background: #f8f9fa; }
        .dept.collapsed + ul { display: none; }
        .active-item { background-color: #007bff !important; color: white !important; }
        .highlight { background-color: #fff3cd !important; border: 1px solid #ffeeba; }

        /* [우측 카드 디자인] */
        .user-card { border: 1px solid #eee; padding: 40px; border-radius: 15px; box-shadow: 0 10px 25px rgba(0,0,0,0.05); max-width: 550px; }
    </style>
</head>
<body>

    <div class="sidebar">
        <h2>🏢 사내 조직도</h2>
        
        <div class="control-btns">
            <button id="btn-expand" class="btn-text">전체 펼치기</button>
            <button id="btn-collapse" class="btn-text">전체 접기</button>
        </div>

        <div class="search-container">
            <input type="text" id="tree-search" placeholder="이름을 입력하세요..." autocomplete="off">
            <button id="btn-search-trigger" class="btn btn-search">검색</button>
            <button id="btn-search-reset" class="btn btn-reset">초기화</button>
            
            <div id="search-results-list"></div>
        </div>

        <ul class="tree" id="main-tree"></ul>
    </div>

    <div class="detail-view">
        <div id="view-empty" style="text-align: center; margin-top: 150px; color: #ccc;">
            <p style="font-size: 80px; margin: 0;">👥</p>
            <p>사원 검색 또는 조직도에서 선택하세요.</p>
        </div>

        <div id="view-detail" style="display: none;">
            <div class="user-card">
                <span id="user-dept-tag" style="background:#e7f1ff; color:#007bff; padding:4px 12px; border-radius:20px; font-size:12px; font-weight:bold;">부서명</span>
                <h1 id="user-name" style="margin: 15px 0 5px 0; font-size: 32px;">이름</h1>
                <p id="user-title" style="margin: 0 0 25px 0; color: #666; font-size: 18px;">직급</p>
                <hr style="border:0; border-top:1px solid #eee; margin-bottom:25px;">
                <p><strong>사번:</strong> <span id="user-id"></span></p>
                <p><strong>이메일:</strong> <span id="user-email"></span></p>
                <p><strong>담당업무:</strong> <span id="user-task"></span></p>
            </div>
        </div>
    </div>

<script>
$(document).ready(function() {
    const orgData = [
        {
            "name": "기술개발본부",
            "type": "dept",
            "children": [
                {
                    "name": "AI팀",
                    "type": "dept",
                    "children": [
                        { "name": "김영감", "type": "user", "title": "팀장", "id": "AI-01", "email": "kim@work.com", "task": "AI 모델링" },
                        { "name": "김리서", "type": "user", "title": "사원", "id": "AI-02", "email": "reser@work.com", "task": "데이터 라벨링" }
                    ]
                },
                { "name": "박서버", "type": "user", "title": "수석", "id": "IT-10", "email": "park@work.com", "task": "인프라 관리" }
            ]
        },
        {
            "name": "운영지원팀",
            "type": "dept",
            "children": [
                { "name": "이총무", "type": "user", "title": "과장", "id": "OP-01", "email": "lee@work.com", "task": "자산 관리" }
            ]
        }
    ];

    function buildTree(data, path = "") {
        let html = "";
        data.forEach(item => {
            if (item.type === "dept") {
                html += `<li><div class="dept">🏢 ${item.name}</div><ul>${buildTree(item.children, item.name)}</ul></li>`;
            } else {
                html += `<li class="user" 
                            data-name="${item.name}" data-title="${item.title}" data-id="${item.id}" 
                            data-dept="${path}" data-email="${item.email}" data-task="${item.task}">
                            👤 ${item.name} ${item.title}</li>`;
            }
        });
        return html;
    }
    $('#main-tree').html(buildTree(orgData));

    // 🚩 검색 및 결과 리스트 생성 로직
    function runSearch() {
        const val = $('#tree-search').val().toLowerCase().trim();
        const $resultsList = $('#search-results-list');
        $resultsList.empty().hide();

        if (!val) return;

        let foundCount = 0;
        const $users = $('.user');

        $users.each(function() {
            const name = $(this).data('name');
            const title = $(this).data('title');
            const dept = $(this).data('dept');

            if (name.toLowerCase().indexOf(val) !== -1) {
                // 결과 리스트에 추가
                $resultsList.append(`<div class="result-item" data-id="${$(this).data('id')}">
                    <strong>${name} ${title}</strong> <span class="dept-name">${dept}</span>
                </div>`);
                foundCount++;
            }
        });

        if (foundCount > 0) {
            $resultsList.show();
        }
    }

    // 결과 아이템 클릭 시 트리에서 해당 인물 선택 및 상세 보기
    $(document).on('click', '.result-item', function() {
        const userId = $(this).data('id');
        const $target = $(`.user[data-id="${userId}"]`);
        
        // 검색 리스트 닫기
        $('#search-results-list').hide();
        
        // 트리에서 해당 인물로 이동 및 강조
        $('.dept').addClass('collapsed').next('ul').hide(); // 일단 다 접음
        $target.parents('ul').show().prev('.dept').removeClass('collapsed'); // 부모만 펼침
        $target.parents('li').show();
        $target.click(); // 실제 트리 아이템 클릭 이벤트 발생
    });

    $('#btn-search-trigger').click(runSearch);
    $('#tree-search').on('keyup', function(e) { 
        if(e.which == 13) runSearch();
        else if($(this).val() === "") $('#search-results-list').hide();
    });

    // 초기화 버튼
    $('#btn-search-reset').click(function() {
        $('#tree-search').val('');
        $('#search-results-list').hide();
        $('.dept, .user').removeClass('active-item');
        $('.dept').removeClass('collapsed').next('ul').show();
        $('#view-detail').hide();
        $('#view-empty').show();
    });

    // 트리 클릭 이벤트
    $(document).on('click', '.dept', function() {
        $(this).toggleClass('collapsed').next('ul').slideToggle(200);
    });

    $(document).on('click', '.user', function(e) {
        e.stopPropagation();
        $('.user').removeClass('active-item');
        $(this).addClass('active-item');

        const d = $(this).data();
        $('#view-empty').hide();
        $('#view-detail').fadeIn(200);
        $('#user-name').text(d.name);
        $('#user-title').text(d.title);
        $('#user-id').text(d.id);
        $('#user-dept-tag').text(d.dept);
        $('#user-email').text(d.email);
        $('#user-task').text(d.task);
    });

    $('#btn-expand').click(() => $('.dept').removeClass('collapsed').next('ul').show());
    $('#btn-collapse').click(() => $('.dept').addClass('collapsed').next('ul').hide());
    
    // 문서 클릭 시 검색 결과 리스트 닫기
    $(document).click(function(e) {
        if (!$(e.target).closest('.search-container').length) {
            $('#search-results-list').hide();
        }
    });
});

</script>
</body>
</html>

 

 

※ 해당 내용은 Google Gmini3.0에서 작성되었습니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함