当前位置: 首页 > backend >正文

GPT对话UI--通义千问API

GPT对话UI

项目介绍

一个基于 GPT 的智能对话界面,提供简洁优雅的用户体验。本项目使用纯前端技术栈实现,无需后端服务器即可运行。

功能特点

  • 💬 实时对话:支持与 AI 进行实时对话交互
  • 🌓 主题切换:支持浅色/深色主题,自动跟随系统设置
  • 📝 Markdown 渲染:AI 回复支持 Markdown 格式,包含代码高亮
  • 💾 本地存储:对话历史保存在本地,刷新页面不会丢失
  • 🔍 智能推荐:每次对话后自动推荐相关问题
  • ⌨️ 快捷操作:支持快捷键发送消息,Shift+Enter 换行
  • 📊 代码优化:支持代码块语法高亮和一键复制
  • 🔧 可配置:支持配置 API 密钥
  • 📱 响应式:适配不同屏幕尺寸
  • 🎨 字体调节:支持动态调整界面字体大小

快速开始

  1. 克隆项目到本地
git clone https://gitee.com/anxwefndu/gpt-chat-ui.git
  1. 打开项目目录
cd gpt-chat-ui
  1. 在浏览器中打开 index.html 文件即可使用

使用说明

  1. 首次使用需要配置 API 密钥

    • 点击左侧边栏的"配置密钥"按钮
    • 输入你的 API 密钥
    • 点击保存即可使用
  2. 基本操作

    • 在输入框输入问题后点击发送或按回车键发送
    • 使用 Shift + Enter 可以在输入框换行
    • 点击推荐问题可以快速发送相关提问
    • 可以通过左侧的滑块调整字体大小
    • 点击主题按钮切换深色/浅色模式
  3. 历史记录

    • 所有对话记录会自动保存在本地
    • 可以通过"清除历史记录"按钮清空所有对话
    • 刷新页面不会丢失历史记录

技术栈

  • HTML5
  • CSS3 (Tailwind CSS)
  • JavaScript
  • Marked.js (Markdown 渲染)
  • Highlight.js (代码高亮)
  • Font Awesome (图标)

注意事项

  • 本项目需要有效的 API 密钥才能正常使用
  • 建议使用现代浏览器访问以获得最佳体验
  • 所有数据均存储在本地,清除浏览器数据会导致历史记录丢失
  • 目前文件上传这一块还没来得及加,后续添加上该块内容

源码下载

GPT对话UI

演示截图

1.系统首页
在这里插入图片描述

2.使用说明
在这里插入图片描述

3.配色API-key
在这里插入图片描述

4.系统首页-暗色
在这里插入图片描述

核心代码

index.html

<!DOCTYPE html>
<html lang="zh"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>AI 智能助手</title><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Pacifico&display=swap" rel="stylesheet"><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"><script src="https://cdn.tailwindcss.com"></script><script src="./resource/marked.min.js"></script><link rel="stylesheet" href="./resource/github.min.css"><script src="./resource/highlight.min.js"></script><script>tailwind.config = {theme: {extend: {colors: {primary: '#4A90E2',secondary: '#E3F2FD','primary-dark': '#2B4C7E','text-dark': '#E2E8F0'  // 暗色主题下的主要文字颜色},borderRadius: {'none': '0px','sm': '2px',DEFAULT: '4px','md': '8px','lg': '12px','xl': '16px','2xl': '20px','3xl': '24px','full': '9999px','button': '4px'}}},darkMode: 'class' // 启用暗色模式}
</script><style>/* 保留原有样式 */.message-bubble {max-width: 80%;margin: 8px 0;padding: 12px 16px;border-radius: 12px;width: fit-content;}.user-message {background-color: #E3F2FD;margin-left: auto;border-top-right-radius: 4px;}.ai-message {background-color: #F5F5F5;margin-right: auto;border-top-left-radius: 4px;}/* 自定义滚动条样式 */.custom-scrollbar::-webkit-scrollbar {width: 8px;}.custom-scrollbar::-webkit-scrollbar-track {background: #f1f1f1;border-radius: 4px;}.custom-scrollbar::-webkit-scrollbar-thumb {background: #c1c1c1;border-radius: 4px;}.custom-scrollbar::-webkit-scrollbar-thumb:hover {background: #a8a8a8;}/* 暗色主题样式 */.dark .message-bubble.ai-message {background-color: #2D3748;}.dark .message-bubble.user-message {background-color: #2B4C7E;}.dark .custom-scrollbar::-webkit-scrollbar-track {background: #1A202C;}.dark .custom-scrollbar::-webkit-scrollbar-thumb {background: #4A5568;}.dark .custom-scrollbar::-webkit-scrollbar-thumb:hover {background: #718096;}input[type="range"] {appearance: none;width: 100%;height: 4px;background: #E5E7EB;border-radius: 2px;}input[type="range"]::-webkit-slider-thumb {appearance: none;width: 16px;height: 16px;background: #4A90E2;border-radius: 50%;cursor: pointer;}/* 添加 Markdown 样式 */.markdown-body {font-size: 1em;line-height: 1.6;}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6 {margin-top: 1.5em;margin-bottom: 0.5em;font-weight: 600;}.markdown-body code {color: #0f172a;padding: 0.2em 0.4em;font-size: 0.9em;background-color: rgba(175, 184, 193, 0.2);border-radius: 6px;}.markdown-body pre {padding: 16px;overflow: auto;border-radius: 6px;background-color: #f6f8fa;margin: 1em 0;}.markdown-body pre code {padding: 0;background-color: #f6f8fa;white-space: pre;font-size: 0.95em;font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;}.dark .markdown-body pre {background-color: #f6f8fa;}/* 代码块内的复制按钮样式 */.copy-button {position: absolute;top: 8px;right: 8px;padding: 4px 8px;font-size: 12px;color: #64748b;background-color: #f1f5f9;border: 1px solid #e2e8f0;border-radius: 4px;opacity: 0;transition: all 0.2s ease;}.copy-button:hover {color: #0f172a;background-color: #e2e8f0;border-color: #cbd5e1;}/* 暗色主题下的复制按钮 */.dark .copy-button {color: #94a3b8;background-color: #1e293b;border-color: #334155;}.dark .copy-button:hover {color: #f1f5f9;background-color: #334155;border-color: #475569;}/* 鼠标悬停在代码块上时显示复制按钮 */.markdown-body pre:hover .copy-button {opacity: 1;}/* 代码高亮主题颜色优化 */.markdown-body code {padding: 0.2em 0.4em;font-size: 0.95em;background-color: #f1f5f9;border-radius: 4px;font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;}.markdown-body ul,.markdown-body ol {padding-left: 2em;margin: 1em 0;}.markdown-body li {margin: 0.5em 0;}.markdown-body p {margin: 1em 0;}.markdown-body blockquote {padding: 0 1em;color: #57606a;border-left: 0.25em solid #d0d7de;margin: 1em 0;}.dark .markdown-body blockquote {color: #8b949e;border-left-color: #3b434b;}.markdown-body table {border-collapse: collapse;margin: 1em 0;width: 100%;}.markdown-body table th,.markdown-body table td {padding: 6px 13px;border: 1px solid #d0d7de;}.dark .markdown-body table th,.dark .markdown-body table td {border-color: #3b434b;}.markdown-body table tr:nth-child(2n) {background-color: #f6f8fa;}.dark .markdown-body table tr:nth-child(2n) {background-color: #161b22;}</style>
</head><body class="bg-white dark:bg-gray-900 transition-colors"><div class="flex h-screen"><!-- 修改侧边栏背景色,使其与主内容区一致 --><aside class="w-64 bg-white dark:bg-gray-900 border-r border-gray-200 dark:border-gray-700 flex flex-col"><div class="p-6 border-b border-gray-200"><h1 class="text-2xl font-['Pacifico'] text-primary">logo</h1></div><nav class="flex-1 p-6 space-y-6"><div class="space-y-2"><label class="text-sm font-medium text-gray-700 dark:text-gray-300">主题模式</label><buttononclick="toggleTheme()"class="flex items-center justify-between w-full px-4 py-2 text-sm text-gray-700 dark:text-gray-300 bg-gray-50 dark:bg-gray-700 rounded-button hover:bg-gray-100 dark:hover:bg-gray-600"><span id="themeText">浅色模式</span><i class="fas fa-sun dark:fa-moon text-primary"></i></button></div><div class="space-y-2"><label class="text-sm font-medium text-gray-700 dark:text-gray-300">字体大小</label><div class="flex items-center space-x-2"><span class="text-xs text-gray-500 dark:text-gray-400"></span><input type="range" min="1" max="3" value="2" class="w-full"><span class="text-xs text-gray-500 dark:text-gray-400"></span></div></div><buttonclass="flex items-center w-full px-4 py-2 text-sm text-white bg-primary dark:bg-primary-dark rounded-button hover:bg-primary/90 dark:hover:bg-primary-dark/80 whitespace-nowrap"><i class="fas fa-trash-alt mr-2"></i>清除历史记录</button><button onclick="showHelp()"class="flex items-center w-full px-4 py-2 text-sm text-gray-700 dark:text-gray-300 bg-gray-50 dark:bg-gray-800 rounded-button hover:bg-gray-100 dark:hover:bg-gray-700 whitespace-nowrap"><i class="fas fa-question-circle mr-2"></i>使用帮助</button><button onclick="showConfig()"class="flex items-center w-full px-4 py-2 text-sm text-gray-700 dark:text-gray-300 bg-gray-50 dark:bg-gray-800 rounded-button hover:bg-gray-100 dark:hover:bg-gray-700 whitespace-nowrap"><i class="fas fa-cog mr-2"></i>配置密钥</button></nav></aside><main class="flex-1 flex flex-col"><div class="flex-1 overflow-y-auto p-6 space-y-4 custom-scrollbar"></div><div class="border-t border-gray-200 dark:border-gray-700 p-6"><div class="relative"><textareaclass="w-full h-24 px-4 py-3 text-gray-700 dark:text-text-dark border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:border-primary resize-none"placeholder="输入你的问题..."></textarea><div class="absolute bottom-3 right-3 flex space-x-2"><button class="p-2 text-gray-400 hover:text-primary dark:hover:text-primary"><i class="fas fa-paperclip"></i></button><button class="px-4 py-2 bg-primary dark:bg-primary-dark text-white rounded-button hover:bg-primary/90 dark:hover:bg-primary-dark/80 whitespace-nowrap">发送 <i class="fas fa-paper-plane ml-2"></i></button></div></div><div class="mt-2 flex flex-wrap gap-2"><span class="px-3 py-1 text-sm text-primary dark:text-gray-300 bg-secondary dark:bg-gray-800 rounded-full cursor-pointer hover:bg-primary hover:text-white dark:hover:bg-primary-dark">如何优化代码?</span><span class="px-3 py-1 text-sm text-primary bg-secondary dark:bg-gray-700 rounded-full cursor-pointer hover:bg-primary hover:text-white">写一篇营销文案</span><span class="px-3 py-1 text-sm text-primary bg-secondary dark:bg-gray-700 rounded-full cursor-pointer hover:bg-primary hover:text-white">数据分析方法</span></div></div></main></div><script>function toggleTheme() {const html = document.documentElement;const themeText = document.getElementById('themeText');const isDark = html.classList.toggle('dark');themeText.textContent = isDark ? '深色模式' : '浅色模式';localStorage.setItem('theme', isDark ? 'dark' : 'light');}// 初始化主题if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {document.documentElement.classList.add('dark');document.getElementById('themeText').textContent = '深色模式';}function callGpt(questionText, onProgress, onDone) {const sk = loadSK();// 获取历史消息记录const messages = loadMessages();// 构建消息历史const messageHistory = messages.map(msg => ({role: msg.role === 'user' ? 'user' : 'assistant',content: msg.content}));// 添加当前问题messageHistory.push({role: 'user',content: questionText});fetch("https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions", {method: "post",headers: {"Content-Type": "application/json","Authorization": `Bearer ${sk}`},body: JSON.stringify({model: "qwen-plus",messages: messageHistory,  // 使用完整的消息历史stream: true}),}).then(response => {const reader = response.body.getReader();const decoder = new TextDecoder('utf-8');let fullText = "";function read() {reader.read().then(({done, value}) => {if (done) {onDone(fullText);return;}const text = decoder.decode(value, {stream: true});const chunks = text.replace("data: [DONE]", "").replace("data: ", "").split("data: ");for (let i = 0; i < chunks.length; i++) {try {const obj = JSON.parse(chunks[i]);const choices = obj.choices;const delta = choices[0].delta;fullText += delta.content;// 调用回调函数,实时更新内容onProgress(fullText);} catch (e) {console.log(chunks[i])read();}}read();}).catch(error => {console.log(error);alert("工具处理出错");});}read();}).catch(error => {console.log(error);alert("工具处理出错:" + error);});}// 消息记录管理const MESSAGE_STORAGE_KEY = 'chat_messages';function loadMessages() {const stored = localStorage.getItem(MESSAGE_STORAGE_KEY);return stored ? JSON.parse(stored) : [];}function saveMessages(messages) {localStorage.setItem(MESSAGE_STORAGE_KEY, JSON.stringify(messages));}function appendMessage(role, content) {const messages = loadMessages();messages.push({role,content,timestamp: new Date().toLocaleTimeString('zh', { hour: '2-digit', minute: '2-digit' })});saveMessages(messages);renderMessages();}function clearMessages() {localStorage.removeItem(MESSAGE_STORAGE_KEY);renderMessages();}// 配置 marked 选项marked.setOptions({highlight: function(code, lang) {if (lang && hljs.getLanguage(lang)) {return hljs.highlight(code, { language: lang }).value;}return code;},breaks: true,gfm: true});function renderMessages() {const messagesContainer = document.querySelector('.custom-scrollbar');const messages = loadMessages();messagesContainer.innerHTML = messages.map(msg => `<div class="message-bubble ${msg.role === 'user' ? 'user-message' : 'ai-message'}"><div class="text-gray-800 dark:text-text-dark markdown-body">${msg.role === 'user' ? msg.content : marked.parse(msg.content)}</div><span class="text-xs text-gray-400 dark:text-gray-500 mt-1 block">${msg.timestamp}</span></div>`).join('');// 处理代码块的高亮和复制功能const codeBlocks = messagesContainer.querySelectorAll('pre code');codeBlocks.forEach(block => {// 应用代码高亮hljs.highlightElement(block);// 添加复制按钮const copyButton = document.createElement('button');copyButton.className = 'copy-button';copyButton.innerHTML = '<i class="fas fa-copy mr-1"></i>复制';copyButton.onclick = async () => {try {await navigator.clipboard.writeText(block.textContent);copyButton.innerHTML = '<i class="fas fa-check mr-1"></i>已复制';setTimeout(() => {copyButton.innerHTML = '<i class="fas fa-copy mr-1"></i>复制';}, 2000);} catch (err) {console.error('复制失败:', err);}};// 为代码块容器添加相对定位const preBlock = block.parentElement;preBlock.style.position = 'relative';preBlock.appendChild(copyButton);});// 滚动到底部messagesContainer.scrollTop = messagesContainer.scrollHeight;}// 发送消息function sendMessage() {const textarea = document.querySelector('textarea');const content = textarea.value.trim();if (!content) return;const sk = loadSK();if (!sk) {alert('请先配置 API 密钥');showConfig();return;}// 添加用户消息appendMessage('user', content);textarea.value = '';// 调用 GPTcallGpt(content, (text) => {const messages = loadMessages();if (messages[messages.length - 1].role === 'assistant') {messages[messages.length - 1].content = text;} else {messages.push({role: 'assistant',content: text,timestamp: new Date().toLocaleTimeString('zh', {hour: '2-digit', minute: '2-digit'})});}saveMessages(messages);renderMessages();}, (finalText) => {console.log('回复完成:', finalText);renderSuggestion();});}// 事件处理document.addEventListener('DOMContentLoaded', () => {const textarea = document.querySelector('textarea');const sendButton = document.querySelector('button:has(.fa-paper-plane)');const clearButton = document.querySelector('button:has(.fa-trash-alt)');const suggestionSpans = document.querySelectorAll('.mt-2.flex.flex-wrap.gap-2 span');// 绑定事件sendButton.addEventListener('click', sendMessage);textarea.addEventListener('keydown', (e) => {if (e.key === 'Enter' && !e.shiftKey) {e.preventDefault();sendMessage();}});// 快捷提问suggestionSpans.forEach(span => {span.addEventListener('click', () => {textarea.value = span.textContent.trim();sendMessage();});});// 初始化消息记录renderMessages();// 修改清除按钮事件clearButton.addEventListener('click', confirmClear);renderSuggestion();});function showHelp() {const helpContent = `<div class="bg-white dark:bg-gray-800 p-6 rounded-lg max-w-2xl mx-auto" style="z-index: 999"><h2 class="text-xl font-bold text-gray-900 dark:text-text-dark mb-4">使用说明</h2><div class="space-y-3 text-gray-700 dark:text-text-dark"><p>1. 在输入框中输入您的问题,点击发送按钮或按回车键发送</p><p>2. 支持快捷提问,点击下方预设的问题直接发送</p><p>3. 可以使用 Shift + Enter 在输入框中换行</p><p>4. 支持深色/浅色主题切换,可根据个人喜好选择</p><p>5. 支持调整字体大小,通过滑块可以设置小、中、大三种字号</p><p>6. 所有对话记录会保存在本地,刷新页面不会丢失</p><p>7. 清除历史记录会删除所有本地保存的对话</p><p>8. 需要配置 API 密钥才能使用对话功能</p><p>9. 每次对话完成后会自动推荐相关的后续问题</p><p>10. 支持实时显示 AI 回复内容</p></div><button onclick="closeHelp()" class="mt-6 px-4 py-2 bg-primary dark:bg-primary-dark text-white rounded-button hover:bg-primary/90 dark:hover:bg-primary-dark/80" style=" margin-left: auto; display: flex; justify-content: right">知道了</button></div><div class="fixed inset-0 bg-black bg-opacity-50 z-40" onclick="closeHelp()"></div>`;const helpDiv = document.createElement('div');helpDiv.id = 'helpModal';helpDiv.className = 'fixed inset-0 flex items-center justify-center z-50';helpDiv.innerHTML = helpContent;document.body.appendChild(helpDiv);}function closeHelp() {const helpModal = document.getElementById('helpModal');if (helpModal) {helpModal.remove();}}function confirmClear() {const confirmContent = `<div class="bg-white s dark:bg-gray-800 p-6 rounded-lg max-w-md mx-auto" style="z-index: 999"><h2 class="text-xl font-bold text-gray-900 dark:text-text-dark mb-4">确认清除</h2><p class="text-gray-700 dark:text-text-dark">确定要清除所有对话记录吗?此操作不可恢复。</p><div class="mt-6 flex space-x-4" style="display: flex; justify-content: right"><button onclick="closeConfirm()" class="px-4 py-2 text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 rounded-button hover:bg-gray-200 dark:hover:bg-gray-600">取消</button><button onclick="clearAndClose()" class="px-4 py-2 bg-red-500 text-white rounded-button hover:bg-red-600">确认清除</button></div></div><div class="fixed inset-0 bg-black bg-opacity-50 z-40" onclick="closeConfirm()"></div>`;const confirmDiv = document.createElement('div');confirmDiv.id = 'confirmModal';confirmDiv.className = 'fixed inset-0 flex items-center justify-center z-50';confirmDiv.innerHTML = confirmContent;document.body.appendChild(confirmDiv);}function closeConfirm() {const confirmModal = document.getElementById('confirmModal');if (confirmModal) {confirmModal.remove();}}function clearAndClose() {clearMessages();closeConfirm();}function renderSuggestion() {const messages = loadMessages();// 获取最近的对话内容if (messages.length > 0) {const recentMessages = messages.slice(-3).map(msg => msg.content).join('\n');getSuggestions(recentMessages, (suggestions) => {const suggestionContainer = document.querySelector('.mt-2.flex.flex-wrap.gap-2');suggestionContainer.innerHTML = suggestions.map(suggestion => `<span class="px-3 py-1 text-sm text-primary dark:text-gray-300 bg-secondary dark:bg-gray-800 rounded-full cursor-pointer hover:bg-primary hover:text-white dark:hover:bg-primary-dark">${suggestion}</span>`).join('');// 重新绑定事件const suggestionSpans = document.querySelectorAll('.mt-2.flex.flex-wrap.gap-2 span');suggestionSpans.forEach(span => {span.addEventListener('click', () => {document.querySelector('textarea').value = span.textContent.trim();sendMessage();});});});}}function getSuggestions(context, callback) {const sk = loadSK();if (!sk) {callback(['如何继续优化这个方案?', '有什么相关的最佳实践?', '还有其他方面需要考虑吗?']);return;}fetch("https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions", {method: "post",headers: {"Content-Type": "application/json","Authorization": `Bearer ${sk}`},body: JSON.stringify({model: "qwen-plus",messages: [{role: "user",content: `基于以下对话内容,推荐3个相关的后续提问,直接返回3个问题,用|||分隔:\n${context}`}],stream: false}),}).then(response => response.json()).then(data => {const suggestions = data.choices[0].message.content.split('|||').map(q => q.trim());callback(suggestions);}).catch(error => {console.error('获取建议问题失败:', error);// 发生错误时使用默认建议callback(['如何继续优化这个方案?', '有什么相关的最佳实践?', '还有其他方面需要考虑吗?']);});}const SK_STORAGE_KEY = 'chat_sk';function loadSK() {return localStorage.getItem(SK_STORAGE_KEY) || '';}function saveSK(sk) {localStorage.setItem(SK_STORAGE_KEY, sk);}function showConfig() {const currentSK = loadSK();const configContent = `<div class="bg-white dark:bg-gray-800 p-6 rounded-lg max-w-md mx-auto" style="z-index: 999; min-width: 500px"><h2 class="text-xl font-bold text-gray-900 dark:text-text-dark mb-4">配置 API 密钥</h2><div class="space-y-4"><div><label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">API 密钥 (SK)</label><input type="password" id="skInput" value="${currentSK}"class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary dark:bg-gray-700 dark:text-white"placeholder="请输入你的 API 密钥"></div><div class="text-sm text-gray-500 dark:text-gray-400">请妥善保管你的 API 密钥,不要泄露给他人。</div></div><div class="mt-6 flex justify-end space-x-4"><button onclick="closeConfig()" class="px-4 py-2 text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 rounded-button hover:bg-gray-200 dark:hover:bg-gray-600">取消</button><button onclick="saveConfig()" class="px-4 py-2 bg-primary dark:bg-primary-dark text-white rounded-button hover:bg-primary/90 dark:hover:bg-primary-dark/80">保存</button></div></div><div class="fixed inset-0 bg-black bg-opacity-50 z-40" onclick="closeConfig()"></div>`;const configDiv = document.createElement('div');configDiv.id = 'configModal';configDiv.className = 'fixed inset-0 flex items-center justify-center z-50';configDiv.innerHTML = configContent;document.body.appendChild(configDiv);}function closeConfig() {const configModal = document.getElementById('configModal');if (configModal) {configModal.remove();}}function saveConfig() {const skInput = document.getElementById('skInput');const sk = skInput.value.trim();if (!sk) {alert('请输入有效的 API 密钥');return;}saveSK(sk);closeConfig();}const FONT_SIZE_KEY = 'chat_font_size';function loadFontSize() {return localStorage.getItem(FONT_SIZE_KEY) || '2';}function saveFontSize(size) {localStorage.setItem(FONT_SIZE_KEY, size);}function updateFontSize(size) {const html = document.documentElement;switch(size) {case '1':html.style.fontSize = '14px';break;case '2':html.style.fontSize = '16px';break;case '3':html.style.fontSize = '18px';break;}}document.addEventListener('DOMContentLoaded', () => {// 初始化字体大小const fontSizeSlider = document.querySelector('input[type="range"]');fontSizeSlider.value = loadFontSize();updateFontSize(fontSizeSlider.value);// 监听字体大小变化fontSizeSlider.addEventListener('change', (e) => {const size = e.target.value;saveFontSize(size);updateFontSize(size);});});</script>
</body></html>
http://www.xdnf.cn/news/77.html

相关文章:

  • Linux 权限
  • 2025.4.17学习日记 初识JavaScript 以及Java和JavaScript有什么区别
  • 什么是分布式锁?
  • Linux: 生产者消费者模型
  • 从零开始学A2A四:A2A 协议的安全性与多模态支持
  • 多个路由器互通(静态路由)无单臂路由(简单版)
  • STM32 时钟树
  • TCP连接建立:为什么是三次握手?
  • 正则表达式在爬虫中的应用:匹配 HTML 和 JSON 的技巧
  • 操作教程|通过DataEase制作MaxKB系统数据大屏
  • QML之Overlay
  • R4打卡——pytorch实现LSTM预测火灾
  • 《vue3学习手记4》
  • openai发布今天发布了o3和o4-mini。
  • Vue 3 reactive 和 ref 区别及 失去响应性问题
  • 大数据常见的模型定义及应用场景建议╮(╯▽╰)╭
  • 深入理解常见排序算法:从原理到实践
  • 视频剪辑入门
  • 深入了解v-model的原理:v-model拆分为value属性和input事件,表单类组件的封装并用v-model简化代码
  • 是德科技E5080B网络分析仪深度评测:5G/车载雷达测试实战指南
  • 零基础上手Python数据分析 (16):DataFrame 常用统计分析方法
  • 【2025“华中杯”大学生数学建模挑战赛】C题:就业状态分析与预测 详细解题思路
  • ffmpeg 添加 nvenc支持
  • Layout 路由
  • 202520读书笔记|《我要按自己喜欢的方式去生活》——面对可能到来的裁员,那就等正式通知吧
  • SAP系统青果糖无法报工
  • 前沿要塞:Vue组件安全工程的防御体系重构与技术突围
  • 介绍 Docker 的基本概念和优势,以及在应用程序开发中的实际应用。
  • 第十六届蓝桥杯大赛软件赛省赛 C++ 大学 B 组 部分题解
  • 解锁智能制造:PLC远程下载如何让设备运维效率提升10倍?