File size: 3,921 Bytes
460bd69
867f974
460bd69
 
867f974
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
460bd69
867f974
460bd69
867f974
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
460bd69
867f974
460bd69
867f974
1681cd4
867f974
460bd69
867f974
 
460bd69
867f974
 
 
 
 
 
 
 
 
 
 
 
 
460bd69
867f974
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
460bd69
867f974
460bd69
867f974
 
 
 
 
460bd69
867f974
460bd69
867f974
460bd69
867f974
460bd69
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('μ•± μ½”μ–΄ λͺ¨λ“ˆ μ΄ˆκΈ°ν™” μ™„λ£Œ');
});