From 2af1b4ffe7473be04a7dd4d82eb06f688be1aac1 Mon Sep 17 00:00:00 2001 From: yczpf2019 Date: Wed, 28 Jan 2026 00:19:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E6=8F=90=E4=BA=A4=EF=BC=9ACo?= =?UTF-8?q?dingRoom=20=E6=9C=BA=E5=99=A8=E4=BA=BA=E4=B8=8E=20AI=20?= =?UTF-8?q?=E5=B9=B3=E5=8F=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 24 +++ App.tsx | 0 README.md | 20 +++ components/ChatBot.tsx | 96 ++++++++++++ components/SVGIcons.tsx | 27 ++++ index.html | 322 ++++++++++++++++++++++++++++++++++++++ index.tsx | 1 + metadata.json | 8 + package.json | 21 +++ services/geminiService.ts | 35 +++++ tsconfig.json | 29 ++++ types.ts | 12 ++ vite.config.ts | 23 +++ 13 files changed, 618 insertions(+) create mode 100644 .gitignore create mode 100644 App.tsx create mode 100644 README.md create mode 100644 components/ChatBot.tsx create mode 100644 components/SVGIcons.tsx create mode 100644 index.html create mode 100644 index.tsx create mode 100644 metadata.json create mode 100644 package.json create mode 100644 services/geminiService.ts create mode 100644 tsconfig.json create mode 100644 types.ts create mode 100644 vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/App.tsx b/App.tsx new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md new file mode 100644 index 0000000..7e7a93a --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +
+GHBanner +
+ +# Run and deploy your AI Studio app + +This contains everything you need to run your app locally. + +View your app in AI Studio: https://ai.studio/apps/temp/1 + +## Run Locally + +**Prerequisites:** Node.js + + +1. Install dependencies: + `npm install` +2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key +3. Run the app: + `npm run dev` diff --git a/components/ChatBot.tsx b/components/ChatBot.tsx new file mode 100644 index 0000000..331a910 --- /dev/null +++ b/components/ChatBot.tsx @@ -0,0 +1,96 @@ + +import React, { useState, useRef, useEffect } from 'react'; +import { getRoboticsChatResponse } from '../services/geminiService'; +import { Message } from '../types'; +import { BrainIcon } from './SVGIcons'; + +const ChatBot: React.FC = () => { + const [messages, setMessages] = useState([]); + const [input, setInput] = useState(''); + const [isLoading, setIsLoading] = useState(false); + const scrollRef = useRef(null); + + useEffect(() => { + if (scrollRef.current) { + scrollRef.current.scrollTop = scrollRef.current.scrollHeight; + } + }, [messages, isLoading]); + + const handleSend = async () => { + if (!input.trim() || isLoading) return; + + const userMsg: Message = { role: 'user', text: input }; + setMessages(prev => [...prev, userMsg]); + setInput(''); + setIsLoading(true); + + const botResponse = await getRoboticsChatResponse(messages, input); + + setMessages(prev => [...prev, { role: 'model', text: botResponse }]); + setIsLoading(false); + }; + + return ( +
+
+ +
+

机器人专家助手

+

由 CodingRoom AI 驱动

+
+
+ +
+ {messages.length === 0 && ( +
+ "你可以问我关于 ROS2、逆运动学,或者如何为你的下一个机器人编程。" +
+ )} + {messages.map((msg, i) => ( +
+
+ {msg.text} +
+
+ ))} + {isLoading && ( +
+
+
+ + + +
+
+
+ )} +
+ +
+
+ setInput(e.target.value)} + onKeyPress={(e) => e.key === 'Enter' && handleSend()} + placeholder="输入你的机器人技术问题..." + className="flex-1 bg-slate-800 border border-slate-700 rounded-lg px-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 text-white" + /> + +
+
+
+ ); +}; + +export default ChatBot; diff --git a/components/SVGIcons.tsx b/components/SVGIcons.tsx new file mode 100644 index 0000000..9e8204b --- /dev/null +++ b/components/SVGIcons.tsx @@ -0,0 +1,27 @@ + +import React from 'react'; + +// Added missing BrainIcon component used in ChatBot header +export const BrainIcon = () => ( + + + +); + +export const CuteRobot = ({ className }: { className?: string }) => ( + + + + + + + + + +); + +export const FunGear = () => ( + + + +); diff --git a/index.html b/index.html new file mode 100644 index 0000000..ed94a7a --- /dev/null +++ b/index.html @@ -0,0 +1,322 @@ + + + + + + + CodingRoom | 机器人与 AI 世界 + + + + + + + + + + + + + + +
+
+
+
+ 🌟 机器人创新工坊 +
+

+ 和机器人朋友
+ + 开启智能新体验 + +

+

+ 在 CodingRoom,我们让机器人变成你的好伙伴!来这里设计你自己的机器人小伙伴,让它学会走路、说话和各种神奇技能! +

+
+ +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + +
+
+
+

三大核心功能

+
+
+
+
+
+ + + +
+

机器人奇遇记

+

挑选最适合你的“机械战友”,开启第一步。

+
+
+
+ + + +
+

智能控制

+

让机器人跳舞、唱歌和灵活绕障。

+
+
+
+ + + +
+

AI 小魔法

+

给机器人装上“超级大脑”!让它认出你的脸。

+
+
+
+
+ + +
+
+
+

为什么大家都爱 CodingRoom?

+
+
+
+ 1
+ 超简单:拖拽即可操控,轻松上手。 +
+
+
+ 2
+ 看得到:指令发出,机器人立刻动起来! +
+
+
+
+
+
+
🤖
+

智能互动,无限可能

+
+
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/index.tsx b/index.tsx new file mode 100644 index 0000000..43ef976 --- /dev/null +++ b/index.tsx @@ -0,0 +1 @@ +// Conversation module removed. \ No newline at end of file diff --git a/metadata.json b/metadata.json new file mode 100644 index 0000000..a5953a7 --- /dev/null +++ b/metadata.json @@ -0,0 +1,8 @@ + +{ + "name": "CodingRoom - 少年机器人奇幻编程", + "description": "专为青少年设计的机器人编程与 AI 启蒙平台,让创意在指尖起飞。", + "requestFramePermissions": [ + "microphone" + ] +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..a19b52f --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "codingroom---少年机器人奇幻编程", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^19.2.4", + "@google/genai": "^1.38.0" + }, + "devDependencies": { + "@types/node": "^22.14.0", + "@vitejs/plugin-react": "^5.0.0", + "typescript": "~5.8.2", + "vite": "^6.2.0" + } +} diff --git a/services/geminiService.ts b/services/geminiService.ts new file mode 100644 index 0000000..3d70d88 --- /dev/null +++ b/services/geminiService.ts @@ -0,0 +1,35 @@ + +import { GoogleGenAI } from "@google/genai"; +import { Message } from "../types"; + +const SYSTEM_INSTRUCTION = `你是 CodingRoom.cn 机器人 AI 助手。 +你是一名亲切的机器人专家,专门为学习者解答机器人、编程和 AI 的奥秘。 +请用通俗易懂、生动有趣的语言回答问题(多用比喻,比如把代码比作魔法,把传感器比作眼睛)。 +在提到我们时,请使用“CodingRoom.cn”或“我们”。 +你的回复必须使用中文。 +如果用户问到 C++ 入门题,请给予鼓励并给出简单清晰的提示。`; + +export const getRoboticsChatResponse = async (history: Message[], userInput: string) => { + const ai = new GoogleGenAI({ apiKey: process.env.API_KEY }); + + try { + const response = await ai.models.generateContent({ + model: 'gemini-3-pro-preview', + contents: [ + ...history.map(m => ({ role: m.role, parts: [{ text: m.text }] })), + { role: 'user', parts: [{ text: userInput }] } + ], + config: { + systemInstruction: SYSTEM_INSTRUCTION, + temperature: 0.8, + topK: 40, + topP: 0.95, + }, + }); + + return response.text || "抱歉,我的机器人脑袋刚才短路了,请再说一遍?"; + } catch (error) { + console.error("Gemini API Error:", error); + return "机器人大脑目前正在充电中,请稍后再试哦!"; + } +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..2c6eed5 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "ES2022", + "experimentalDecorators": true, + "useDefineForClassFields": false, + "module": "ESNext", + "lib": [ + "ES2022", + "DOM", + "DOM.Iterable" + ], + "skipLibCheck": true, + "types": [ + "node" + ], + "moduleResolution": "bundler", + "isolatedModules": true, + "moduleDetection": "force", + "allowJs": true, + "jsx": "react-jsx", + "paths": { + "@/*": [ + "./*" + ] + }, + "allowImportingTsExtensions": true, + "noEmit": true + } +} \ No newline at end of file diff --git a/types.ts b/types.ts new file mode 100644 index 0000000..5305585 --- /dev/null +++ b/types.ts @@ -0,0 +1,12 @@ +import React from 'react'; + +export interface Message { + role: 'user' | 'model'; + text: string; +} + +export interface Service { + title: string; + description: string; + icon: React.ReactNode; +} \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..ee5fb8d --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,23 @@ +import path from 'path'; +import { defineConfig, loadEnv } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig(({ mode }) => { + const env = loadEnv(mode, '.', ''); + return { + server: { + port: 3000, + host: '0.0.0.0', + }, + plugins: [react()], + define: { + 'process.env.API_KEY': JSON.stringify(env.GEMINI_API_KEY), + 'process.env.GEMINI_API_KEY': JSON.stringify(env.GEMINI_API_KEY) + }, + resolve: { + alias: { + '@': path.resolve(__dirname, '.'), + } + } + }; +});