File size: 3,921 Bytes
6575706
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/**
 * RAG 검색 챗봇 UI 곡톡 μœ ν‹Έλ¦¬ν‹° JavaScript
 */

// μ „μ—­ μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜
const AppUtils = {
    // μ‹œμŠ€ν…œ μ•Œλ¦Ό λ©”μ‹œμ§€ μΆ”κ°€
    addSystemNotification: function(message) {
        console.log(`[μ‹œμŠ€ν…œ μ•Œλ¦Ό] ${message}`);
        
        const messageDiv = document.createElement('div');
        messageDiv.classList.add('message', 'system');
        
        const contentDiv = document.createElement('div');
        contentDiv.classList.add('message-content');
        
        const messageP = document.createElement('p');
        messageP.innerHTML = `<i class="fas fa-info-circle"></i> ${message}`;
        contentDiv.appendChild(messageP);
        
        messageDiv.appendChild(contentDiv);
        
        // μ±„νŒ… λ©”μ‹œμ§€ μ˜μ—­μ΄ 있으면 μΆ”κ°€
        const chatMessages = document.getElementById('chatMessages');
        if (chatMessages) {
            chatMessages.appendChild(messageDiv);
            // μŠ€ν¬λ‘€μ„ κ°€μž₯ μ•„λž˜λ‘œ 이동
            chatMessages.scrollTop = chatMessages.scrollHeight;
        }
    },
    
    // 였λ₯˜ λ©”μ‹œμ§€ μΆ”κ°€
    addErrorMessage: function(errorText) {
        console.error(`[였λ₯˜] ${errorText}`);
        
        const messageDiv = document.createElement('div');
        messageDiv.classList.add('message', 'system');
        
        const contentDiv = document.createElement('div');
        contentDiv.classList.add('message-content');
        contentDiv.style.backgroundColor = 'rgba(239, 68, 68, 0.1)';
        contentDiv.style.color = 'var(--error-color)';
        
        const errorP = document.createElement('p');
        errorP.innerHTML = `<i class="fas fa-exclamation-circle"></i> ${errorText}`;
        contentDiv.appendChild(errorP);
        
        messageDiv.appendChild(contentDiv);
        
        // μ±„νŒ… λ©”μ‹œμ§€ μ˜μ—­μ΄ 있으면 μΆ”κ°€
        const chatMessages = document.getElementById('chatMessages');
        if (chatMessages) {
            chatMessages.appendChild(messageDiv);
            // μŠ€ν¬λ‘€μ„ κ°€μž₯ μ•„λž˜λ‘œ 이동
            chatMessages.scrollTop = chatMessages.scrollHeight;
        }
    },
    
    // νƒ€μž„μ•„μ›ƒ κΈ°λŠ₯이 μžˆλŠ” fetch
    fetchWithTimeout: async function(url, options = {}, timeout = 30000) {
        console.log(`API μš”μ²­: ${options.method || 'GET'} ${url}`);
        
        const controller = new AbortController();
        const id = setTimeout(() => controller.abort(), timeout);
        
        try {
            const response = await fetch(url, {
                ...options,
                signal: controller.signal
            });
            clearTimeout(id);
            console.log(`API 응닡 μƒνƒœ: ${response.status}`);
            return response;
        } catch (error) {
            clearTimeout(id);
            if (error.name === 'AbortError') {
                console.error(`API μš”μ²­ νƒ€μž„μ•„μ›ƒ: ${url}`);
                throw new Error('μš”μ²­ μ‹œκ°„μ΄ μ΄ˆκ³Όλ˜μ—ˆμŠ΅λ‹ˆλ‹€.');
            }
            console.error(`API μš”μ²­ μ‹€νŒ¨: ${url}`, error);
            throw error;
        }
    },
    
    // λ‘œλ”© μŠ€ν”Όλ„ˆ HTML 생성
    createLoadingSpinner: function() {
        return '<div class="loading-spinner"></div>';
    },
    
    // λ‚ μ§œ ν¬λ§·νŒ…
    formatDate: function(date) {
        return new Date(date).toLocaleString('ko-KR', {
            year: 'numeric',
            month: '2-digit',
            day: '2-digit',
            hour: '2-digit',
            minute: '2-digit'
        });
    },
    
    // HTML λ¬Έμžμ—΄ μ΄μŠ€μΌ€μ΄ν”„ (XSS λ°©μ§€)
    escapeHtml: function(html) {
        const div = document.createElement('div');
        div.textContent = html;
        return div.innerHTML;
    }
};

// νŽ˜μ΄μ§€ λ‘œλ“œ μ™„λ£Œ μ‹œ 곡톡 μ΄ˆκΈ°ν™”
document.addEventListener('DOMContentLoaded', function() {
    console.log('μ•± μ½”μ–΄ λͺ¨λ“ˆ μ΄ˆκΈ°ν™” μ™„λ£Œ');
});