以下是一个增强版纯前端实现方案,支持文件上传和内容解析功能,直接调用DeepSeek API:
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>DeepSeek 智能助手 (支持附件)</title><style>:root {--primary-color: #2c3e50;--accent-color: #3498db;--error-color: #e74c3c;}body {font-family: 'Segoe UI', system-ui, sans-serif;max-width: 800px;margin: 2rem auto;padding: 0 20px;background: #f8f9fa;}.container {background: white;border-radius: 12px;box-shadow: 0 4px 6px rgba(0,0,0,0.1);padding: 2rem;}.input-group {display: flex;gap: 10px;margin-bottom: 1rem;}input[type="text"], input[type="file"] {flex: 1;padding: 12px;border: 2px solid #ddd;border-radius: 8px;font-size: 16px;}button {padding: 12px 24px;background: var(--accent-color);color: white;border: none;border-radius: 8px;cursor: pointer;transition: opacity 0.3s;}button:hover {opacity: 0.9;}#file-list {margin: 1rem 0;padding: 0;list-style: none;}.file-item {display: flex;align-items: center;padding: 8px;background: #f8f9fa;border-radius: 6px;margin-bottom: 6px;}.file-item span {flex: 1;font-size: 0.9em;}#response {margin-top: 20px;padding: 16px;background: #f8f9fa;border-radius: 8px;min-height: 100px;white-space: pre-wrap;line-height: 1.6;}.loading {display: none;color: #666;font-style: italic;}.error {color: var(--error-color);margin: 0.5rem 0;}</style>
</head>
<body><div class="container"><h1 style="color: var(--primary-color); margin-bottom: 1.5rem;">DeepSeek 智能助手</h1><!-- 文件上传区域 --><div class="input-group"><input type="file" id="file-input" multiple accept=".txt,.pdf,.docx"><button onclick="handleFileUpload()">上传文件</button></div><ul id="file-list"></ul><!-- 问答区域 --><div class="input-group"><input type="text" id="question" placeholder="请输入您的问题..."><button onclick="askQuestion()">发送</button></div><div class="loading" id="loading">处理中...</div><div id="response"></div></div><script>// 配置参数(⚠️ 安全提示:前端暴露API密钥仅限本地测试)const CONFIG = {API_KEY: 'your-api-key-here',API_URL: 'https://api.deepseek.com/v1/chat/completions',MODEL: 'deepseek-chat',MAX_FILE_SIZE: 2 * 1024 * 1024, // 2MBALLOWED_TYPES: ['text/plain', 'application/pdf', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document']}let uploadedFiles = [];// 文件上传处理async function handleFileUpload() {const fileInput = document.getElementById('file-input');const files = Array.from(fileInput.files);const fileList = document.getElementById('file-list');try {for (const file of files) {// 验证文件if (file.size > CONFIG.MAX_FILE_SIZE) {throw new Error(`文件 ${file.name} 超过大小限制 (最大 ${CONFIG.MAX_FILE_SIZE/1024/1024}MB)`);}if (!CONFIG.ALLOWED_TYPES.includes(file.type)) {throw new Error(`不支持的文件类型: ${file.type}`);}// 读取文件内容const content = await readFileContent(file);// 存储文件信息uploadedFiles.push({name: file.name,type: file.type,size: file.size,content: content,uploadedAt: new Date().toISOString()});// 更新文件列表const li = document.createElement('li');li.className = 'file-item';li.innerHTML = `<span>${file.name} (${formatFileSize(file.size)})</span><button onclick="removeFile('${file.name}')">删除</button>`;fileList.appendChild(li);}fileInput.value = ''; // 清空选择} catch (error) {showError(error.message);}}// 文件内容读取function readFileContent(file) {return new Promise((resolve, reject) => {const reader = new FileReader();reader.onload = () => resolve(reader.result);reader.onerror = reject;if (file.type === 'application/pdf') {// PDF处理需要第三方库(此处简化处理)reader.readAsArrayBuffer(file);} else {reader.readAsText(file, 'UTF-8');}});}// 提问处理async function askQuestion() {const question = document.getElementById('question').value.trim();const loading = document.getElementById('loading');const responseDiv = document.getElementById('response');if (!question) {showError('请输入有效问题');return;}try {loading.style.display = 'block';responseDiv.textContent = '';// 构建上下文const context = uploadedFiles.length > 0 ? `参考文件内容:\n${uploadedFiles.map(f => f.content).join('\n')}\n\n问题:`: '';// API请求const response = await fetch(CONFIG.API_URL, {method: 'POST',headers: {'Content-Type': 'application/json','Authorization': `Bearer ${CONFIG.API_KEY}`},body: JSON.stringify({model: CONFIG.MODEL,messages: [{role: "user",content: context + question}]})});if (!response.ok) throw new Error(`API请求失败: ${response.status}`);const data = await response.json();responseDiv.textContent = data.choices[0].message.content;} catch (error) {showError(error.message);console.error(error);} finally {loading.style.display = 'none';}}// 辅助函数function formatFileSize(bytes) {if (bytes < 1024) return bytes + ' B';if (bytes < 1048576) return (bytes/1024).toFixed(1) + ' KB';return (bytes/1048576).toFixed(1) + ' MB';}function removeFile(filename) {uploadedFiles = uploadedFiles.filter(f => f.name !== filename);document.querySelectorAll('.file-item').forEach(li => {if (li.textContent.includes(filename)) li.remove();});}function showError(message) {const errorDiv = document.createElement('div');errorDiv.className = 'error';errorDiv.textContent = message;document.body.appendChild(errorDiv);setTimeout(() => errorDiv.remove(), 3000);}// 事件监听document.getElementById('question').addEventListener('keypress', e => {if (e.key === 'Enter') askQuestion();});</script>
</body>
</html>
功能亮点:
-
文件上传管理:
- 支持多文件上传 (PDF/DOCX/TXT)
- 实时显示文件列表
- 文件大小和类型验证
- 单个文件删除功能
-
内容处理:
- 自动将文件内容作为上下文附加到问题
- 基础PDF/DOCX文件处理(需扩展解析逻辑)
-
安全控制:
- 文件大小限制 (2MB)
- 允许的文件类型白名单
使用说明:
- 保存为
.html
文件 - 替换API密钥
- 通过以下方式访问:
访问 http://localhost:8000# 使用Python启动简易服务器 python3 -m http.server 8000
扩展建议:
- 增强文件解析(需引入库):
<!-- 在<head>添加 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.4.120/pdf.min.js"></script>
<script src="https://unpkg.com/mammoth@1.4.8/mammoth.browser.min.js"></script><script>
// 修改readFileContent函数
async function readFileContent(file) {if (file.type === 'application/pdf') {const arrayBuffer = await file.arrayBuffer();const pdf = await pdfjsLib.getDocument(arrayBuffer).promise;let text = '';for (let i = 1; i <= pdf.numPages; i++) {const page = await pdf.getPage(i);const content = await page.getTextContent();text += content.items.map(item => item.str).join(' ');}return text;} else if (file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {const arrayBuffer = await file.arrayBuffer();const result = await mammoth.extractRawText({arrayBuffer});return result.value;}return await file.text();
}
</script>
- 添加预览功能:
function previewFile(filename) {const file = uploadedFiles.find(f => f.name === filename);if (file) {const win = window.open();win.document.write(`<pre>${file.content}</pre>`);}
}
- 添加会话管理:
// 在CONFIG中添加
SESSION_MAX_AGE: 3600 // 1小时有效期// 初始化时读取本地存储
if (localStorage.getItem('chatSession')) {const session = JSON.parse(localStorage.getItem('chatSession'));if (Date.now() - session.timestamp < CONFIG.SESSION_MAX_AGE * 1000) {uploadedFiles = session.files;// 更新文件列表显示...}
}// 定期保存
setInterval(() => {localStorage.setItem('chatSession', JSON.stringify({files: uploadedFiles,timestamp: Date.now()}));
}, 30000);
注意事项:
- 前端文件处理能力有限,大文件可能影响性能
- 复杂文档解析建议在服务端进行
- API密钥需通过后端服务保护(正式环境)
- 浏览器内存限制:建议添加文件数量限制
项目下载地址:
调用DeepSeek API 增强版纯前端实现方案,支持文件上传和内容解析功能