办学质量监测教学评价系统
ageer
2025-04-14 a4314dbbdefa806e923d1fd18016a7469804e0e2
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AI 对话助手</title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 min-h-screen">
<div class="container mx-auto p-4 max-w-3xl">
    <!-- 标题 -->
    <div class="text-center mb-8">
        <h1 class="text-3xl font-bold text-gray-800">AI 对话助手</h1>
        <p class="text-gray-600 mt-2">基于 Spring AI 的流式对话系统 By AhuCodingBeast</p>
    </div>
 
    <!-- 聊天容器 -->
    <div id="chat-container" class="bg-white rounded-xl shadow-lg p-4 mb-4 h-[500px] overflow-y-auto space-y-4">
        <!-- 初始欢迎消息 -->
        <div class="ai-message flex items-start gap-3">
            <div class="bg-green-100 p-3 rounded-lg max-w-[85%]">
                <span class="text-gray-800">您好!我是AI助手,有什么可以帮您?</span>
            </div>
        </div>
    </div>
 
    <!-- 输入区域 -->
    <div class="flex gap-2">
        <input type="text" id="message-input"
               class="flex-1 border border-gray-300 rounded-xl px-4 py-3 focus:outline-none focus:ring-2 focus:ring-blue-500"
               placeholder="输入您的问题...">
        <button id="send-button"
                class="bg-blue-500 text-white px-6 py-3 rounded-xl hover:bg-blue-600 transition-colors flex items-center">
            <span>发送</span>
            <svg id="loading-spinner" class="hidden w-4 h-4 ml-2 animate-spin" fill="none" viewBox="0 0 24 24">
                <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
                <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path>
            </svg>
        </button>
    </div>
</div>
 
<script>
    const chatContainer = document.getElementById('chat-container');
    const messageInput = document.getElementById('message-input');
    const sendButton = document.getElementById('send-button');
    const loadingSpinner = document.getElementById('loading-spinner');
 
    // 发送消息处理
    function handleSend() {
        const message = messageInput.value.trim();
        if (!message) return;
 
        // 添加用户消息
        addMessage(message, 'user');
        messageInput.value = '';
 
        // 构建API URL
        const apiUrl = new URL('http://localhost:9999/dashscope/chat-client/generate_stream');
        apiUrl.searchParams.append('id', '01');
        apiUrl.searchParams.append('prompt', message);
 
        // 显示加载状态
        sendButton.disabled = true;
        loadingSpinner.classList.remove('hidden');
 
        // 创建EventSource连接
        const eventSource = new EventSource(apiUrl);
        let aiMessageElement = null;
 
        eventSource.onmessage = (event) => {
            try {
                const data = JSON.parse(event.data);
                console.log(data);
                const content = data.result?.output?.text || '';
                const finishReason = data.result?.metadata?.finishReason;
 
                // 创建消息容器(如果不存在)
                if (!aiMessageElement) {
                    aiMessageElement = addMessage('', 'ai');
                }
 
                // 追加内容
                if (content) {
                    aiMessageElement.querySelector('.message-content').textContent += content;
                    autoScroll();
                }
 
                // 处理结束
                if (finishReason === 'STOP') {
                    eventSource.close();
                    sendButton.disabled = false;
                    loadingSpinner.classList.add('hidden');
                }
            } catch (error) {
                console.error('解析错误:', error);
            }
        };
 
        eventSource.onerror = (error) => {
            console.error('连接错误:', error);
            eventSource.close();
            sendButton.disabled = false;
            loadingSpinner.classList.add('hidden');
            addMessage('对话连接异常,请重试', 'ai', true);
        };
    }
 
    // 添加消息到容器
    function addMessage(content, type, isError = false) {
        const messageDiv = document.createElement('div');
        messageDiv.className = `${type}-message flex items-start gap-3`;
 
        const bubble = document.createElement('div');
        bubble.className = `p-3 rounded-lg max-w-[85%] ${
            type === 'user'
                ? 'bg-blue-500 text-white ml-auto'
                : `bg-green-100 ${isError ? 'text-red-500' : 'text-gray-800'}`
        }`;
 
        const contentSpan = document.createElement('span');
        contentSpan.className = 'message-content';
        contentSpan.textContent = content;
 
        bubble.appendChild(contentSpan);
        messageDiv.appendChild(bubble);
        chatContainer.appendChild(messageDiv);
 
        autoScroll();
        return bubble;
    }
 
    // 自动滚动到底部
    function autoScroll() {
        chatContainer.scrollTop = chatContainer.scrollHeight;
    }
 
    // 事件监听
    sendButton.addEventListener('click', handleSend);
    messageInput.addEventListener('keypress', (e) => {
        if (e.key === 'Enter' && !e.shiftKey) {
            e.preventDefault();
            handleSend();
        }
    });
</script>
</body>
</html>