网站首页 > 文章精选 正文
谷歌AI手机桌面运行代码平台:https://codepen.io/ttcssxep-the-selector/pen/ByBQqQo可以复制以下的代码,在这个平台上面去运行,输入你的谷歌官方模型api,这样就可以聊天了。
谷歌官方API申请:https://aistudio.google.com/app/apikey
谷歌AI手机桌面开源代码↓
<!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>
<style>
body {
font-family: sans-serif;
margin: 0;
padding: 0;
background-color: #f0f0f0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
transition: background-color 0.5s ease;
}
.chat-container {
position: fixed;
bottom: 0;
right: 0;
background-color: #fff;
border-radius: 10px 10px 0 0;
box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
width: 100%;
max-width: 600px;
height: 80vh;
max-height: 800px;
display: flex;
flex-direction: column;
border: 1px solid #ddd;
transition: background-color 0.5s ease, color 0.5s ease;
}
.chat-header {
display: flex;
flex-direction: column;
padding: 15px;
border-bottom: 1px solid #ddd;
background-color: #f9f9f9;
}
.chat-settings {
display: flex;
gap: 10px;
flex-wrap: wrap;
align-items: center;
}
.chat-settings select,
.chat-settings input {
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
flex: 1;
min-width: 150px;
}
.chat-buttons {
display: flex;
gap: 10px;
margin-top: 10px;
flex-wrap: wrap;
}
.chat-buttons button {
background-color: #eee;
cursor: pointer;
transition: background-color 0.3s ease;
white-space: nowrap;
border: 1px solid #ddd;
border-radius: 5px;
padding: 10px;
flex: 1;
min-width: 80px;
}
.chat-buttons button:hover {
background-color: #ddd;
}
.chat-messages {
flex-grow: 1;
padding: 15px;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 15px;
background-color: #fafafa;
height: calc(80vh - 200px); /* 调整高度以适应固定窗口 */
}
.message-container {
display: flex;
align-items: center;
position: relative;
}
.message-container:hover .copy-button {
opacity: 1;
}
.message {
padding: 10px 15px;
border-radius: 20px;
max-width: 75%;
word-wrap: break-word;
transition: background-color 0.3s ease;
white-space: pre-line;
font-size: 1em;
}
.copy-button {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
background-color: transparent;
border: none;
cursor: pointer;
font-size: 14px;
opacity: 0;
transition: opacity 0.3s ease;
padding: 5px 10px;
border-radius: 5px;
background-color: #f0f0f0;
}
.copy-button:hover {
background-color: #e0e0e0;
}
.user-message {
background-color: #DCF8C6;
align-self: flex-end;
color: #333;
}
.ai-message {
background-color: #E5E5EA;
align-self: flex-start;
color: #333;
}
.chat-input {
display: flex;
padding: 15px;
border-top: 1px solid #ddd;
background-color: #f9f9f9;
}
.chat-input input {
flex-grow: 1;
border: 1px solid #ccc;
border-radius: 5px;
padding: 10px;
margin-right: 10px;
font-size: 1em;
}
.chat-input button {
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
padding: 10px 15px;
cursor: pointer;
font-size: 1em;
}
.chat-input button:hover {
background-color: #0056b3;
}
.error-message {
color: red;
font-size: 0.9em;
margin-top: 5px;
text-align: center;
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: none;
align-items: center;
justify-content: center;
z-index: 1000;
}
.color-options, .memory-options, .history-options, .save-chat-overlay {
background-color: #fff;
padding: 25px;
border-radius: 10px;
display: flex;
flex-wrap: wrap;
gap: 15px;
max-width: 400px;
width: 90%;
}
.color-option {
width: 35px;
height: 35px;
border-radius: 50%;
cursor: pointer;
border: 1px solid #ddd;
transition: border 0.3s ease;
}
.color-option:hover {
border: 2px solid #999;
}
.memory-options, .history-options {
flex-direction: column;
}
.history-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
border-bottom: 1px solid #ddd;
}
.history-item:last-child {
border-bottom: none;
}
.history-item button {
background-color: #ff4d4d;
color: white;
border: none;
border-radius: 5px;
padding: 7px 12px;
cursor: pointer;
}
.history-item button:hover {
background-color: #e60000;
}
.history-item span {
flex-grow: 1;
margin-right: 10px;
word-break: break-word;
}
.save-chat-overlay input {
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
width: 100%;
margin-bottom: 15px;
font-size: 1em;
}
.save-chat-overlay button {
background-color: #28a745;
color: white;
border: none;
border-radius: 5px;
padding: 10px 15px;
cursor: pointer;
margin-bottom: 10px;
font-size: 1em;
}
.save-chat-overlay button:hover {
background-color: #218838;
}
@media (max-width: 600px) {
.chat-container {
width: 100%;
height: 80vh;
border-radius: 10px 10px 0 0;
max-width: none;
max-height: none;
}
}
</style>
</head>
<body>
<div class="chat-container">
<div class="chat-header">
<div class="chat-settings">
<select id="modelSelect">
<option value="gemini-pro">gemini-pro</option>
<option value="gemini-exp-1114">gemini-exp-1114</option>
<option value="learnlm-1.5-pro-experimental">learnlm-1.5-pro-experimental</option>
<option value="gemini-exp-1206">gemini-exp-1206</option>
<option value="gemini-2.0-flash-exp">gemini-2.0-flash-exp</option>
<option value="gemini-exp-1121">gemini-exp-1121</option>
</select>
<input type="text" id="apiKeyInput" placeholder="输入API Key">
</div>
<div class="chat-buttons">
<button id="changeColorButton">主题</button>
<button id="memoryButton">记忆</button>
<button id="chatHistoryButton">聊天记录</button>
<button id="clearChatButton">清空</button>
</div>
</div>
<div class="chat-messages" id="chatMessages">
<!-- 消息将动态添加到这里 -->
</div>
<div class="chat-input">
<input type="text" id="messageInput" placeholder="输入消息...">
<button id="sendButton">发送</button>
</div>
</div>
<div id="errorMessage" class="error-message" style="display: none;"></div>
<!-- 主题选择 -->
<div id="colorOverlay" class="overlay">
<div class="color-options" id="colorOptions">
<!-- 颜色选项将动态添加到这里 -->
</div>
</div>
<!-- 记忆设置 -->
<div id="memoryOverlay" class="overlay">
<div class="memory-options">
<select id="memorySizeSelect">
<option value="10">保存最近10组对话</option>
<option value="50">保存最近50组对话</option>
<option value="100">保存最近100组对话</option>
</select>
<button id="saveMemoryButton">保存记忆</button>
<button id="clearMemoryButton">清除记忆</button>
</div>
</div>
<!-- 聊天记录 -->
<div id="chatHistoryOverlay" class="overlay">
<div class="history-options">
<h3>聊天记录</h3>
<div id="historyList">
<!-- 历史记录项将动态添加到这里 -->
</div>
<button id="closeHistoryButton">关闭</button>
</div>
</div>
<!-- 保存聊天 -->
<div id="saveChatOverlay" class="overlay">
<div class="save-chat-overlay">
<h3>保存当前聊天</h3>
<input type="text" id="chatTitleInput" placeholder="输入聊天标题">
<button id="saveChatButton">保存</button>
<button id="cancelSaveChatButton">取消</button>
</div>
</div>
<script type="module">
import { GoogleGenerativeAI } from "https://esm.run/@google/generative-ai";
const modelSelect = document.getElementById('modelSelect');
const apiKeyInput = document.getElementById('apiKeyInput');
const messageInput = document.getElementById('messageInput');
const sendButton = document.getElementById('sendButton');
const chatMessages = document.getElementById('chatMessages');
const errorMessageDiv = document.getElementById('errorMessage');
const changeColorButton = document.getElementById('changeColorButton');
const clearChatButton = document.getElementById('clearChatButton');
const chatHistoryButton = document.getElementById('chatHistoryButton');
const colorOverlay = document.getElementById('colorOverlay');
const colorOptions = document.getElementById('colorOptions');
const memoryButton = document.getElementById('memoryButton');
const memoryOverlay = document.getElementById('memoryOverlay');
const memorySizeSelect = document.getElementById('memorySizeSelect');
const saveMemoryButton = document.getElementById('saveMemoryButton');
const clearMemoryButton = document.getElementById('clearMemoryButton');
const chatHistoryOverlay = document.getElementById('chatHistoryOverlay');
const historyList = document.getElementById('historyList');
const closeHistoryButton = document.getElementById('closeHistoryButton');
const saveChatOverlay = document.getElementById('saveChatOverlay');
const chatTitleInput = document.getElementById('chatTitleInput');
const saveChatButton = document.getElementById('saveChatButton');
const cancelSaveChatButton = document.getElementById('cancelSaveChatButton');
const backgroundColors = [
'#f0f0f0', '#e0e0e0', '#d0d0d0', '#c0c0c0', '#b0b0b0',
'#a0a0a0', '#909090', '#808080', '#707070', '#606060',
'#f8bbd0','#f06292','#e91e63', '#9c27b0',
'#673ab7','#3f51b5','#2196f3', '#03a9f4',
'#00bcd4', '#009688', '#4caf50', '#8bc34a'
];
const textColors = [
'#333', '#444', '#555', '#666', '#777',
'#888', '#999', '#aaa', '#bbb', '#ccc',
'#000', '#1a237e','#4a148c','#0d47a1',
'#01579b','#004d40','#1b5e20','#33691e',
'#bf360c', '#d84315', '#ff6f00',
'#ff8f00'
];
const chatContainer = document.querySelector('.chat-container');
let currentBackgroundColorIndex = 0;
let currentTextColorIndex = 0;
let chatHistory = []; // 当前聊天会话的消息
let memorySize = localStorage.getItem('memorySize') || '10';
// 初始化API Key
document.addEventListener('DOMContentLoaded', () => {
const savedApiKey = localStorage.getItem('apiKey');
if (savedApiKey) {
apiKeyInput.value = savedApiKey;
}
loadChatHistory();
});
memoryButton.addEventListener('click', () => {
memoryOverlay.style.display = 'flex';
});
memoryOverlay.addEventListener('click', (event) => {
if(event.target === memoryOverlay){
memoryOverlay.style.display = 'none';
}
});
saveMemoryButton.addEventListener('click', () => {
memorySize = memorySizeSelect.value;
localStorage.setItem('memorySize', memorySize);
memoryOverlay.style.display = 'none';
showError(`记忆大小已设置为保存最近${memorySize}组对话。`);
setTimeout(hideError, 3000);
});
clearMemoryButton.addEventListener('click', () => {
if (confirm("确定要清除所有聊天记录吗?")) {
localStorage.removeItem('chatSessions');
localStorage.removeItem('apiKey');
showError("所有聊天记录和API Key已清除。");
setTimeout(hideError, 3000);
chatHistory = [];
chatMessages.innerHTML = '';
apiKeyInput.value = '';
}
memoryOverlay.style.display = 'none';
});
changeColorButton.addEventListener('click', () => {
colorOverlay.style.display = 'flex';
});
colorOverlay.addEventListener('click', (event) => {
if(event.target === colorOverlay) {
colorOverlay.style.display = 'none';
}
});
function changeColorTheme(bgColor, textColor) {
document.body.style.backgroundColor = bgColor;
chatContainer.style.backgroundColor = bgColor;
chatContainer.style.color = textColor;
}
function createColorOptions() {
colorOptions.innerHTML = '';
for (let i = 0; i < backgroundColors.length; i++) {
const colorDiv = document.createElement('div');
colorDiv.classList.add('color-option');
colorDiv.style.backgroundColor = backgroundColors[i];
colorDiv.addEventListener('click', () => {
currentBackgroundColorIndex = i;
currentTextColorIndex = i;
changeColorTheme(backgroundColors[currentBackgroundColorIndex], textColors[currentTextColorIndex]);
colorOverlay.style.display = 'none';
});
colorOptions.appendChild(colorDiv);
}
}
createColorOptions();
chatHistoryButton.addEventListener('click', () => {
loadChatSessions();
chatHistoryOverlay.style.display = 'flex';
});
chatHistoryOverlay.addEventListener('click', (event) => {
if(event.target === chatHistoryOverlay){
chatHistoryOverlay.style.display = 'none';
}
});
closeHistoryButton.addEventListener('click', () => {
chatHistoryOverlay.style.display = 'none';
});
saveChatOverlay.addEventListener('click', (event) => {
if(event.target === saveChatOverlay){
saveChatOverlay.style.display = 'none';
}
});
saveChatButton.addEventListener('click', () => {
const title = chatTitleInput.value.trim();
if (!title) {
alert('请为聊天会话输入一个标题。');
return;
}
saveCurrentChatSession(title);
chatTitleInput.value = '';
saveChatOverlay.style.display = 'none';
showError("聊天会话已保存。");
setTimeout(hideError, 3000);
});
cancelSaveChatButton.addEventListener('click', () => {
chatTitleInput.value = '';
saveChatOverlay.style.display = 'none';
});
clearChatButton.addEventListener('click', () => {
if (chatHistory.length === 0) {
alert("当前聊天记录已为空。");
return;
}
if (confirm("是否保存当前聊天记录?")) {
saveChatOverlay.style.display = 'flex';
} else {
chatMessages.innerHTML = '';
chatHistory = [];
showError("聊天记录已清空。");
setTimeout(hideError, 3000);
}
});
function loadChatHistory() {
const storedSessions = localStorage.getItem('chatSessions');
if (storedSessions) {
const sessions = JSON.parse(storedSessions);
const activeSession = sessions.find(session => session.isActive);
if (activeSession) {
chatHistory = activeSession.messages;
activeSession.messages.forEach(entry => {
appendMessage(entry.sender, entry.text, false);
});
updateActiveSession(activeSession.id);
}
}
}
sendButton.addEventListener('click', async () => {
const message = messageInput.value.trim();
let apiKey = apiKeyInput.value.trim();
const selectedModel = modelSelect.value;
if (!apiKey) {
showError("请先输入 API Key。");
return;
}
if (!message) {
showError("请输入消息。");
return;
}
hideError();
// 保存API Key到localStorage
localStorage.setItem('apiKey', apiKey);
appendMessage('user', message, true);
chatHistory.push({ sender: 'user', text: message });
saveChatHistory();
messageInput.value = '';
try {
let aiResponse = await sendToAI(message, apiKey, selectedModel, chatHistory);
aiResponse = aiResponse.replace(/\*/g, ''); // 去除星号
typeWriter(aiResponse, 'ai');
chatHistory.push({ sender: 'ai', text: aiResponse });
saveChatHistory();
} catch (error) {
showError(`AI回复失败: ${error.message}`);
appendMessage('ai', "AI回复失败,请稍后重试", true);
}
});
async function sendToAI(message, apiKey, model, history) {
try {
const genAI = new GoogleGenerativeAI(apiKey);
const generativeModel = genAI.getGenerativeModel({ model: model });
const prompt = history.map(item => `${item.sender}: ${item.text}`).join('\n') + `\nuser: ${message}`;
const result = await generativeModel.generateContent(prompt);
if (result && result.response && result.response.text) {
return result.response.text();
} else {
throw new Error("无效的 AI 回复");
}
} catch (error) {
console.error("Error during AI response:", error);
throw error;
}
}
function saveChatHistory() {
let sessions = JSON.parse(localStorage.getItem('chatSessions')) || [];
const activeSessionIndex = sessions.findIndex(session => session.isActive);
if (activeSessionIndex !== -1) {
sessions[activeSessionIndex].messages = chatHistory;
} else {
const newSession = {
id: Date.now(),
title: `未命名会话 ${sessions.length + 1}`,
messages: chatHistory,
isActive: true
};
sessions.push(newSession);
}
if (sessions.length > parseInt(memorySize, 10)) {
sessions = sessions.slice(-parseInt(memorySize, 10));
}
localStorage.setItem('chatSessions', JSON.stringify(sessions));
}
function saveCurrentChatSession(title) {
let sessions = JSON.parse(localStorage.getItem('chatSessions')) || [];
sessions.forEach(session => session.isActive = false);
const newSession = {
id: Date.now(),
title: title,
messages: chatHistory,
isActive: true
};
sessions.push(newSession);
if (sessions.length > parseInt(memorySize, 10)) {
sessions = sessions.slice(-parseInt(memorySize, 10));
}
localStorage.setItem('chatSessions', JSON.stringify(sessions));
}
function loadChatSessions() {
historyList.innerHTML = '';
const sessions = JSON.parse(localStorage.getItem('chatSessions')) || [];
if (sessions.length === 0) {
historyList.innerHTML = '<p>暂无聊天记录。</p>';
return;
}
sessions.forEach(session => {
const itemDiv = document.createElement('div');
itemDiv.classList.add('history-item');
const titleSpan = document.createElement('span');
titleSpan.textContent = session.title;
itemDiv.appendChild(titleSpan);
const loadButton = document.createElement('button');
loadButton.textContent = '加载';
loadButton.addEventListener('click', () => {
loadSession(session.id);
chatHistoryOverlay.style.display = 'none';
});
itemDiv.appendChild(loadButton);
const deleteButton = document.createElement('button');
deleteButton.textContent = '删除';
deleteButton.addEventListener('click', () => {
if (confirm(`确定要删除 "${session.title}" 吗?`)) {
deleteSession(session.id);
loadChatSessions();
}
});
itemDiv.appendChild(deleteButton);
historyList.appendChild(itemDiv);
});
}
function loadSession(id) {
const sessions = JSON.parse(localStorage.getItem('chatSessions')) || [];
const session = sessions.find(s => s.id === id);
if (session) {
sessions.forEach(s => s.isActive = false);
session.isActive = true;
localStorage.setItem('chatSessions', JSON.stringify(sessions));
chatHistory = session.messages;
chatMessages.innerHTML = '';
chatHistory.forEach(entry => {
appendMessage(entry.sender, entry.text, false);
});
}
}
function deleteSession(id) {
let sessions = JSON.parse(localStorage.getItem('chatSessions')) || [];
sessions = sessions.filter(s => s.id !== id);
localStorage.setItem('chatSessions', JSON.stringify(sessions));
const activeSession = sessions.find(s => s.isActive);
if (!activeSession) {
chatHistory = [];
chatMessages.innerHTML = '';
}
}
function appendMessage(sender, text, shouldScroll = true) {
const messageContainer = document.createElement('div');
messageContainer.classList.add('message-container');
const messageDiv = document.createElement('div');
messageDiv.classList.add('message');
messageDiv.classList.add(sender + '-message');
messageDiv.innerText = text;
messageContainer.appendChild(messageDiv);
const copyButton = document.createElement('button');
copyButton.classList.add('copy-button');
copyButton.innerText = '复制';
copyButton.addEventListener('click', () => {
copyToClipboard(text);
});
messageContainer.appendChild(copyButton);
chatMessages.appendChild(messageContainer);
if (shouldScroll) {
chatMessages.scrollTo({
top: chatMessages.scrollHeight,
behavior: 'smooth'
});
}
}
function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => {
alert('文本已复制');
}).catch(err => {
console.error('复制失败', err);
alert('复制失败,请稍后重试');
});
}
function typeWriter(text, sender) {
const messageContainer = document.createElement('div');
messageContainer.classList.add('message-container');
const messageDiv = document.createElement('div');
messageDiv.classList.add('message');
messageDiv.classList.add(sender + '-message');
messageContainer.appendChild(messageDiv);
const copyButton = document.createElement('button');
copyButton.classList.add('copy-button');
copyButton.innerText = '复制';
copyButton.addEventListener('click', () => {
copyToClipboard(text);
});
messageContainer.appendChild(copyButton);
chatMessages.appendChild(messageContainer);
// 滚动到最新消息
chatMessages.scrollTo({
top: chatMessages.scrollHeight,
behavior: 'smooth'
});
let i = 0;
const intervalId = setInterval(() => {
if (i < text.length) {
messageDiv.textContent += text.charAt(i);
i++;
chatMessages.scrollTo({
top: chatMessages.scrollHeight,
behavior: 'smooth'
});
} else {
clearInterval(intervalId);
}
}, 30);
}
function showError(message) {
errorMessageDiv.textContent = message;
errorMessageDiv.style.display = 'block';
}
function hideError() {
errorMessageDiv.style.display = 'none';
errorMessageDiv.textContent = "";
}
// 允许按 Enter 键发送消息
messageInput.addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
sendButton.click();
}
});
</script>
</body>
</html>
- 上一篇: 前端进阶高薪必看-CSS篇
- 下一篇: 第02节:导入Element-plus组件完成Layout布局
猜你喜欢
- 2025-01-04 「炫丽」从0开始做一个WPF+Blazor对话小程序
- 2025-01-04 adonisjs的模板以及路由
- 2025-01-04 5、谈谈你对BFC的理解?
- 2025-01-04 前端 BFC、IFC、GFC 和 FFC,这些你都知道吗?
- 2025-01-04 Wijmo5 Flexgrid基础教程:自定义编辑器
- 2025-01-04 H5小游戏开发教程之页面基础布局的开发
- 2025-01-04 web前端:CSS的常用属性速查表
- 2025-01-04 用网页做个ppt- 定时全屏切换图片
- 2025-01-04 HTML翻牌器:用CSS和HTML元素创造动态数字展示
- 2025-01-04 「网络安全」安全设备篇(漏洞扫描器-流量监控-安全审计产品)
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 稳压管的稳压区是工作在什么区 (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)