尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

基于React与Gemini API构建动态MBTI测试网站的全栈实践

基于React与Gemini API构建动态MBTI测试网站的全栈实践 1. 项目概述当MBTI遇上AI一次有趣的“手搓”实践最近MBTI人格测试又火了起来身边的朋友、同事都在讨论自己是“INFP”还是“ENTJ”。作为一个喜欢折腾的前端开发者我就在想能不能自己动手做一个既好看又好玩的MBTI测试网站传统的测试题大多是静态的结果也相对固定。这次我决定玩点不一样的用Google最新的Gemini大模型作为“大脑”来动态生成测试题目并解析结果再配上React和Tailwind CSS搭建一个高颜值的交互界面。这个项目的核心思路很简单用户通过网站进行一系列有趣的互动这些交互数据会被实时发送给Gemini API。Gemini扮演一个“资深心理分析师”的角色它基于我的预设提示词Prompt和用户的实时选择动态生成后续问题并在测试结束后提供一份个性化、带有描述性语言的人格类型分析报告。整个过程不再是做一套固定的题库而更像是一次与AI的对话式探索。最终效果让我挺满意的网站视觉清新流畅交互顺滑而Gemini生成的报告也常常有让人会心一笑的精准描述。这不仅仅是一个玩具项目它完整串联了前端界面开发、AI API集成、提示词工程这几个当前非常热门的技术点。无论你是想学习React全栈实践还是对如何“调教”大模型Prompt Engineering感兴趣亦或是单纯想做一个有趣的个人项目这个案例都有不少可借鉴的地方。下面我就把从零搭建这个“高颜值MBTI测试网站”的全过程包括核心思路、技术细节、踩过的坑以及完整的提示词设计毫无保留地分享出来。2. 技术选型与整体架构设计在动手写代码之前合理的选型和架构设计能事半功倍。我的目标是快速构建一个美观、响应式且逻辑清晰的全栈应用。2.1 前端技术栈React Vite Tailwind CSS为什么是这套组合拳React作为主流的前端框架其组件化思想非常适合构建这种多步骤、状态复杂的交互式应用。测试的每一步欢迎页、题目页、加载页、结果页都可以拆分成独立的组件状态管理清晰。从热词也能看出React相关的面试题、学习资料非常丰富生态成熟。Vite作为下一代前端构建工具它的启动速度和热更新速度远超传统的Webpack。对于这种个人项目追求极致的开发体验非常重要Vite能让你“码”得飞快。用npm create vitelatest就能快速搭建一个ReactTypeScript的项目模板。Tailwind CSS这是实现“高颜值”的关键。它是一个实用优先的CSS框架允许你通过组合类名来快速构建UI。我不需要为每个元素单独写CSS文件直接在JSX里通过类名就能定义样式开发效率极高并且能轻松实现响应式设计和一致的视觉风格。例如一个圆角渐变按钮可能只需要className“px-6 py-3 bg-gradient-to-r from-blue-500 to-purple-600 text-white font-semibold rounded-lg shadow-md hover:shadow-lg transition-shadow”这样一行代码。这个组合是目前前端社区非常流行的高效开发范式能保证在拥有优秀用户体验的同时保持代码的现代性和可维护性。2.2 后端与AI集成Serverless Function Gemini API项目需要与Gemini API通信但直接在前端调用存在暴露API密钥的巨大安全风险。因此我需要一个轻量级的后端作为代理。Serverless Function无服务器函数这是最优雅的解决方案。我不需要维护一台完整的服务器只需要写一个处理特定请求如/api/analyze-mbti的函数。云服务商如Vercel、Netlify、Google Cloud Functions会在请求到来时执行它完成后就释放资源。成本低部署简单。具体实现我会在项目中创建一个api/目录里面放置一个函数文件例如analyze-mbti.ts。这个函数负责接收前端发送的用户交互数据然后使用安全的服务器环境变量中存储的GEMINI_API_KEY去调用Google AI Studio的API。Google Gemini API选择Gemini 1.5 Flash或Pro模型。Flash模型性价比高、响应快非常适合这种交互式对话场景。Pro模型能力更强但成本也更高。对于MBTI测试Flash模型完全够用。你需要去 Google AI Studio 获取API Key。整体数据流设计如下用户在前端React应用点击选择答案。React组件状态更新收集当前轮次的所有选择。用户点击“查看结果”前端将收集到的数据通过fetch发送到我们部署的Serverless Function端点如/api/analyze-mbti。Serverless Function收到请求验证后将用户数据结合我精心设计的系统提示词System Prompt组装成符合Gemini API格式的消息并发起请求。Gemini API返回生成的MBTI类型和详细分析文本。Serverless Function将结果返回给前端。前端React组件收到结果渲染出美观的报告页面。注意绝对不要将GEMINI_API_KEY硬编码在客户端JavaScript中或提交到GitHub等公开仓库。务必使用环境变量在本地创建.env.local文件在部署平台设置环境变量。2.3 项目结构规划一个清晰的项目结构有助于长期维护。我的项目目录大致如下mbti-gemini-app/ ├── public/ # 静态资源 ├── src/ │ ├── components/ # React组件 │ │ ├── Welcome.jsx # 欢迎页 │ │ ├── QuestionCard.jsx # 问题卡片 │ │ ├── OptionButton.jsx # 选项按钮 │ │ ├── LoadingSpinner.jsx # 加载动画 │ │ └── ResultDisplay.jsx # 结果展示 │ ├── pages/ # 页面组件可选 │ │ └── TestPage.jsx # 主要的测试流程页面 │ ├── hooks/ # 自定义Hook如用于API调用 │ │ └── useMBTIAnalysis.js │ ├── utils/ # 工具函数 │ │ └── promptTemplates.js # 提示词模板 │ ├── styles/ # 全局样式Tailwind补足 │ ├── App.jsx # 应用根组件 │ └── main.jsx # 应用入口 ├── api/ # Serverless Functions (Vercel/Netlify) │ └── analyze-mbti.js # 处理分析的API路由 ├── .env.local # 本地环境变量.gitignore ├── vite.config.js # Vite配置 ├── tailwind.config.js # Tailwind配置 └── package.json这样的结构将UI组件、业务逻辑、工具函数和API路由分离职责明确。3. 核心实现从零搭建React前端界面前端界面是用户直接交互的部分美观和流畅至关重要。我们使用React来管理整个测试流程的状态。3.1 使用State管理测试流程测试流程可以抽象为几个状态‘welcome’‘questioning’‘loading’‘result’。我们可以用一个状态变量来控制当前渲染哪个组件。// 在 TestPage.jsx 或 App.jsx 中 import { useState } from react; import Welcome from ‘../components/Welcome’; import QuestionCard from ‘../components/QuestionCard’; import LoadingSpinner from ‘../components/LoadingSpinner’; import ResultDisplay from ‘../components/ResultDisplay’; function TestPage() { const [testStage, setTestStage] useState(‘welcome’); // ‘welcome’, ‘questioning’, ‘loading’, ‘result’ const [userSelections, setUserSelections] useState([]); // 存储用户每一轮的选择 const [mbtiResult, setMbtiResult] useState(null); // 存储Gemini返回的结果 const handleStartTest () { setTestStage(‘questioning’); // 可以在这里初始化第一轮问题或者由Gemini动态生成 }; const handleAnswerSelect (answer) { // 1. 将当前答案存入 userSelections const newSelections […userSelections, answer]; setUserSelections(newSelections); // 2. 判断是否继续提问这里可以设定固定轮数如5轮或由后端决定。 // 本例假设进行3轮交互后提交 if (newSelections.length 3) { setTestStage(‘loading’); // 3. 调用API进行分析 analyzeSelections(newSelections); } else { // 4. 否则更新问题这里可以先模拟理想情况是后端根据历史返回新问题 // 例如从一个本地问题库中取出下一个问题 // setCurrentQuestion(getNextQuestion()); } }; const analyzeSelections async (selections) { try { const response await fetch(‘/api/analyze-mbti’, { method: ‘POST’, headers: { ‘Content-Type’: ‘application/json’ }, body: JSON.stringify({ selections }), }); const data await response.json(); setMbtiResult(data); // data 应包含 { type: ‘INFP’, analysis: ‘…’ } setTestStage(‘result’); } catch (error) { console.error(‘分析失败:’, error); // 处理错误状态 setTestStage(‘error’); } }; // 根据状态渲染不同组件 return ( div className“min-h-screen bg-gradient-to-br from-gray-50 to-blue-50 p-4 md:p-8” {testStage ‘welcome’ Welcome onStart{handleStartTest} /} {testStage ‘questioning’ ( QuestionCard // currentQuestion{currentQuestion} // 传递当前问题 onSelect{handleAnswerSelect} / )} {testStage ‘loading’ LoadingSpinner /} {testStage ‘result’ mbtiResult ( ResultDisplay result{mbtiResult} onRestart{() { setTestStage(‘welcome’); setUserSelections([]); }} / )} /div ); } export default TestPage;3.2 使用Tailwind CSS打造高颜值组件Tailwind的魅力在于快速实现设计。以下是一些关键组件的样式思路Welcome.jsx (欢迎页):function Welcome({ onStart }) { return ( div className“max-w-2xl mx-auto text-center py-12 px-4” h1 className“text-4xl md:text-5xl font-bold text-gray-800 mb-6” 探索你的 span className“bg-gradient-to-r from-purple-600 to-pink-500 bg-clip-text text-transparent” 人格宇宙 /span /h1 p className“text-lg text-gray-600 mb-8 leading-relaxed” 这不是一份传统的问卷。我们将通过几个轻松的场景选择借助AI的力量为你勾勒出独特的MBTI人格画像。 /p button onClick{onStart} className“px-8 py-3 text-lg font-semibold text-white bg-gradient-to-r from-cyan-500 to-blue-600 rounded-full shadow-lg hover:shadow-xl hover:scale-105 transition-all duration-300 focus:outline-none focus:ring-4 focus:ring-blue-300” 开始探索 /button div className“mt-12 grid grid-cols-2 md:grid-cols-4 gap-4” {/* 可以放一些MBTI类型图标或装饰性元素 */} {[‘ISTJ’, ‘ENFP’, ‘INTJ’, ‘ESFJ’].map((type) ( div key{type} className“p-4 bg-white/70 backdrop-blur-sm rounded-xl shadow-sm border border-gray-200” div className“text-2xl font-bold text-gray-700”{type}/div div className“text-sm text-gray-500”16型人格之一/div /div ))} /div /div ); }QuestionCard.jsx (问题卡片): 问题卡片需要清晰展示场景和选项。选项按钮需要提供良好的反馈。function QuestionCard({ /* question, */ onSelect }) { // 假设 question 对象包含 { id, text, options: [{id, text}] } const question { id: 1, text: “周末朋友突然提议去一个热闹的派对但你原本计划在家看书。你会更倾向于”, options: [ { id: ‘a’, text: “欣然同意改变计划去派对享受即兴的社交乐趣。” }, { id: ‘b’, text: “委婉拒绝坚持自己的阅读计划享受独处的宁静时光。” }, ], }; return ( div className“max-w-xl mx-auto bg-white rounded-2xl shadow-xl p-6 md:p-8” div className“mb-2 text-sm font-medium text-blue-600”场景 {question.id}/div h2 className“text-xl md:text-2xl font-bold text-gray-800 mb-8 leading-snug” {question.text} /h2 div className“space-y-4” {question.options.map((option) ( button key{option.id} onClick{() onSelect(option)} className“w-full text-left p-4 rounded-lg border-2 border-gray-200 hover:border-blue-400 hover:bg-blue-50 transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent” div className“flex items-center” div className“flex-shrink-0 w-8 h-8 flex items-center justify-center rounded-full bg-gray-100 text-gray-700 font-medium mr-4” {option.id.toUpperCase()} /div div className“text-gray-700”{option.text}/div /div /button ))} /div div className“mt-8 pt-6 border-t border-gray-200 text-center text-sm text-gray-500” 选择最贴近你本能反应的选项。没有对错之分。 /div /div ); }LoadingSpinner.jsx (加载动画): 加载状态需要让用户感知到AI正在“思考”设计一个优雅的动画很重要。function LoadingSpinner() { return ( div className“max-w-md mx-auto text-center py-16” div className“inline-block relative” {/* 外圈旋转环 */} div className“w-20 h-20 border-4 border-blue-200 border-t-blue-600 rounded-full animate-spin”/div {/* 内圈点缀 */} div className“absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2” div className“w-8 h-8 bg-gradient-to-r from-cyan-400 to-blue-500 rounded-full opacity-80”/div /div /div p className“mt-6 text-lg font-medium text-gray-700”AI正在分析你的选择…/p p className“mt-2 text-sm text-gray-500”正在结合MBTI理论生成你的专属人格报告/p {/* 可以加一些随机出现的趣味文案 */} div className“mt-8 text-xs text-gray-400”“正在解码你的决策偏好…”/div /div ); }通过组合这些组件并利用Tailwind的实用类进行微调一个视觉上吸引人、交互流畅的前端界面就初具雏形了。关键在于保持色彩协调、间距舒适以及交互动画的自然。4. 灵魂所在设计驱动Gemini的提示词系统前端是皮囊AI提示词才是项目的灵魂。如何让Gemini理解MBTI并根据用户有限的交互给出合理的判断是项目成败的关键。这属于**提示词工程Prompt Engineering**的范畴。4.1 系统提示词设计定义AI的角色与任务系统提示词System Instruction用于设定AI的“人设”和对话边界。它会在每次API调用时被发送指导Gemini的行为。我的核心提示词结构如下你是一位资深的MBTI人格分析专家精通迈尔斯-布里格斯类型指标理论。你的任务是根据用户在一系列场景下的选择推断其最可能的MBTI人格类型并提供一份生动、详细、积极的分析报告。 **核心规则** 1. **输出格式**你必须且只能输出一个纯粹的JSON对象包含两个字段type 和 analysis。 2. **类型确定**type 字段的值必须是标准的4字母MBTI代码如 “INFP”, “ESTJ” 等共16种可能。 3. **分析报告**analysis 字段是一段不少于300字的文本。内容需包含 a) **人格类型解读**用通俗易懂的语言解释该类型的核心特征能量方向、信息收集、决策方式、生活态度。 b) **与选择的关联**简要说明用户的哪些选择体现了这些倾向。 c) **优势与潜力**描述该类型可能拥有的独特优势和潜在的发展方向。 d) **风格化描述**用一句比喻或意象来总结例如“你像是一位…的建造者/探险家/守护者”。 e) 语气需积极、鼓励、富有洞察力避免负面标签和绝对化判断。 **分析逻辑参考** - **E (外向) / I (内向)**关注用户选择中体现的能量来源是外部世界社交、行动还是内部世界独处、反思。 - **S (实感) / N (直觉)**关注用户是更注重具体事实、细节和实际经验S还是更关注模式、可能性和抽象概念N。 - **T (思维) / F (情感)**关注用户做决定时是依据逻辑、客观标准T还是依据价值观、人际关系和谐F。 - **J (判断) / P (感知)**关注用户对待外部世界是倾向于计划、有序、决断J还是灵活、适应、开放P。 **用户的选择历史将以数组形式提供给你。请基于以上规则进行专业分析。**这个提示词做了几件关键事明确角色让AI进入“专家”状态。严格格式化输出要求返回JSON方便前端解析。这是与AI协作的黄金法则之一确保数据可程序化处理。定义分析维度将MBTI的四个维度拆解成AI可以理解的判断标准。规定报告结构确保生成的内容丰富、有用且风格统一。4.2 用户消息构建传递交互上下文系统提示词是固定的而用户消息User Message则携带了每次测试的独特数据。当Serverless Function调用Gemini API时需要这样组装对话历史{ “contents”: [ { “role”: “user”, // 实际上第一部分通常是“system”角色但Gemini API的格式可能略有不同。这里用user示意逻辑。 “parts”: [{ “text”: “【上面那一段系统提示词】” }] }, { “role”: “user”, “parts”: [{ “text”: “以下是一位用户在测试中的选择序列请根据这些选择进行分析\n\n1. 场景‘周末计划被打断’用户选择‘欣然同意改变计划去派对享受即兴的社交乐趣。’\n2. 场景‘处理复杂问题’用户选择‘先列出所有已知事实和数据一步步推导。’\n3. 场景‘团队冲突时’用户选择‘主动调解努力让每个人都感到被尊重和理解。’” }] } ] }在实际代码中我们需要动态生成用户选择部分的文本。将userSelections数组格式化成清晰的文本描述对于AI理解至关重要。4.3 提示词迭代与调优心得第一版提示词写出来AI的返回结果可能不尽如人意。可能需要反复调整问题1类型判断过于武断或跳跃。比如用户两个选择偏E一个选择偏FAI可能直接给出“ENFP”但忽略了其他维度。调优在系统提示词中加强“综合判断”和“倾向性”的描述。强调“根据整体选择模式推断最可能的类型”并说明“四个维度是独立的需分别评估”。问题2分析报告千篇一律像维基百科。调优在提示词中增加“避免教科书式定义”、“结合用户的具体选择举例”、“使用生动、个性化的比喻”等要求。甚至可以提供一两个优秀的分析样例。问题3偶尔不遵守JSON格式。调优这是大模型常见的“叛逆”。除了在提示词中用加粗、强调外可以在代码层设置重试和解析后处理逻辑。如果返回的不是合法JSON可以尝试提取其中的MBTI代码和分析文本或者让AI重新生成。实操心得与Gemini等大模型协作清晰的指令和严格的输出格式约束是成功的关键。把AI想象成一个能力极强但需要精确引导的新手员工你的提示词就是给他的工作说明书。说明书越详细、越结构化他的工作成果就越可靠。5. 后端集成实现安全的Serverless API前端和提示词都准备好了现在需要搭建桥梁。我们将创建一个Serverless Function它部署在云端安全地调用Gemini API。5.1 使用Vercel或Netlify部署API路由以Vercel为例在项目根目录创建/api/analyze-mbti.js文件。Vercel会自动将这个目录下的文件识别为Serverless Function。首先安装Google Generative AI的Node.js SDKnpm install google/generative-ai然后编写API函数// /api/analyze-mbti.js import { GoogleGenerativeAI } from “google/generative-ai”; // 从环境变量读取API密钥 const genAI new GoogleGenerativeAI(process.env.GEMINI_API_KEY); export default async function handler(req, res) { // 1. 只允许POST请求 if (req.method ! ‘POST’) { return res.status(405).json({ error: ‘Method not allowed’ }); } // 2. 获取用户数据 const { selections } req.body; if (!selections || !Array.isArray(selections)) { return res.status(400).json({ error: ‘Invalid request data’ }); } try { // 3. 获取模型使用Gemini 1.5 Flash性价比高 const model genAI.getGenerativeModel({ model: “gemini-1.5-flash” }); // 4. 构建提示词 const systemPrompt 【此处粘贴4.1节设计的完整系统提示词】; const userSelectionsText selections.map((sel, idx) ${idx 1}. ${sel.text}).join(‘\n’); const userMessage 以下是一位用户在测试中的选择序列请根据这些选择进行分析\n\n${userSelectionsText}; // 5. 调用Gemini API const result await model.generateContent([ { role: ‘user’, parts: [{ text: systemPrompt }] }, // 注意Gemini API可能用‘user’角色传递系统指令具体看SDK文档 { role: ‘user’, parts: [{ text: userMessage }] }, ]); const response await result.response; const aiText response.text(); // 6. 解析AI返回的文本期望是JSON let parsedResult; try { // 尝试从返回文本中提取JSON部分AI有时会在JSON外加引号或说明 const jsonMatch aiText.match(/\{[\s\S]*\}/); parsedResult jsonMatch ? JSON.parse(jsonMatch[0]) : JSON.parse(aiText); } catch (parseError) { console.error(‘Failed to parse AI response as JSON:’, aiText); // 简易回退尝试寻找MBTI类型代码 const mbtiMatch aiText.match(/\b[IE][NS][TF][JP]\b/); parsedResult { type: mbtiMatch ? mbtiMatch[0] : ‘UNKNOWN’, analysis: aiText, // 返回原始文本作为分析 }; } // 7. 返回结果给前端 res.status(200).json(parsedResult); } catch (error) { console.error(‘Error calling Gemini API:’, error); res.status(500).json({ error: ‘Failed to analyze personality’ }); } }5.2 环境变量配置与安全API密钥必须保密。在本地项目根目录创建.env.local文件GEMINI_API_KEYyour_actual_gemini_api_key_here在package.json中确保这个文件被.gitignore忽略。部署到Vercel时需要在Vercel项目的设置Settings - Environment Variables中添加同名的环境变量。重要安全实践永远不要将API密钥提交到代码仓库。在Serverless Function中可以通过process.env.VARIABLE_NAME安全访问。Vercel/Netlify等平台的环境变量在运行时被注入是安全的。可以在API函数开头添加简单的CORS头以允许你的前端域名访问如果前后端不同域res.setHeader(‘Access-Control-Allow-Origin’, ‘https://your-frontend-domain.com’); res.setHeader(‘Access-Control-Allow-Methods’, ‘POST’);5.3 测试与调试API在本地开发时可以使用工具如curl或 Postman 测试你的API端点。首先在本地运行开发服务器如npm run dev然后你的API路由通常在http://localhost:3000/api/analyze-mbti。一个测试请求的示例使用curlcurl -X POST http://localhost:3000/api/analyze-mbti \ -H “Content-Type: application/json” \ -d ‘{“selections”: [{“text”: “选择A的内容”}, {“text”: “选择B的内容”}]}’观察返回的JSON数据是否符合预期。调试阶段多打印日志确保数据流转正确。6. 项目优化与高级功能探讨基础版本完成后可以从多个角度进行优化提升用户体验和项目深度。6.1 性能与用户体验优化前端状态持久化使用localStorage或sessionStorage保存测试进度。这样用户即使不小心刷新页面也能回到刚才的测试点。加载状态优化除了旋转动画可以设计分步加载提示如“分析能量倾向…”、“解读决策模式…”让等待过程更有趣。结果页分享功能生成结果图片或专属链接。可以使用html2canvas库将结果组件转换为图片方便用户保存或分享到社交媒体。渐进式Web应用PWA使用Vite的PWA插件让网站可以安装到手机桌面获得近似原生应用的体验。6.2 提示词与AI交互进阶动态问题生成目前的例子是固定问题。更高级的玩法是让Gemini根据用户的历史回答动态生成下一个问题。这需要将API调用嵌入到每一轮交互中并将之前的问答历史作为上下文传入。提示词需要调整为“根据用户至今的选择如下提出一个能帮助进一步区分其[E/I, S/N…]维度的新场景问题。”多轮对话与澄清如果AI对某个维度的判断信心不足可以在报告中体现出来例如“你的选择在‘思维(T)’与‘情感(F)’维度上比较均衡这可能意味着你在不同情境下会灵活运用两种决策方式。”支持中文与文化适配确保提示词和场景问题更符合中文语境和文化背景避免直接翻译带来的生硬感。6.3 可扩展性思考多模型支持除了Gemini可以轻松接入OpenAI的GPT系列或国内的大模型在API层做一个适配器让用户或管理员可以选择不同的“分析师”。结果数据库在Serverless Function后端连接一个数据库如Supabase、Firestore匿名存储测试结果不包含个人身份信息。这样可以进行有趣的聚合分析比如“本周最受欢迎的人格类型是什么”。A/B测试对不同的提示词版本或问题集进行A/B测试看看哪种组合得出的结果用户满意度更高。7. 部署上线与踩坑实录将项目部署到线上让所有人都能访问是最后一步。7.1 使用Vercel一键部署Vercel对React Serverless Function的项目支持极好。将代码推送到GitHub仓库。登录 Vercel 点击“New Project”导入你的仓库。在配置页面Vercel会自动检测出是Vite项目。它需要设置环境变量在环境变量配置栏填入GEMINI_API_KEY及其值。点击“Deploy”。几分钟后你的网站就拥有了一个*.vercel.app的域名。部署后访问你的网站进行完整的端到端测试。7.2 常见问题与解决方案问题1API返回错误 “API key not valid”排查检查环境变量GEMINI_API_KEY在Vercel项目中是否配置正确是否有空格或拼写错误。确保在Google AI Studio中已启用API。解决重新生成API Key并在Vercel中更新。问题2前端调用API出现CORS错误排查前端域名如localhost:3000与后端API域名如your-app.vercel.app不同源。解决在Serverless Function的响应中添加CORS头部如5.2节所示。对于Vercel也可以配置vercel.json文件。问题3Gemini返回的内容格式不稳定有时不是JSON排查大语言模型并非完美遵守指令。解决如5.1节代码所示实现一个健壮的解析层。先用正则表达式尝试提取JSON失败后再尝试寻找MBTI代码最后回退到使用原始文本。并在前端做好容错处理。问题4网站加载速度慢特别是结果页等待时间长排查Gemini API调用通常需要1-3秒网络延迟可能加剧。解决优化提示词更精确的指令可能让AI更快组织好语言。前端骨架屏在结果页加载时先显示一个报告的大致骨架灰色占位块提升感知速度。考虑缓存对于完全相同的选择序列可以考虑在Serverless Function端进行短期缓存如使用内存或Redis但注意用户选择的多样性可能使缓存命中率不高。问题5移动端样式错乱排查Tailwind的响应式类如md:可能未覆盖所有情况。解决充分利用Tailwind的移动优先断点。多使用w-fullmax-w-flex-col/flex-row等。在真机或浏览器开发者工具的移动设备模拟模式上反复测试。这个项目从构思到上线的过程是一次非常棒的全栈实践。它涵盖了现代前端开发、无服务器架构、AI应用集成和产品设计思维。最大的收获不是做出了一个网站而是学会了如何将不同的技术模块像拼图一样组合起来解决一个具体而有趣的问题。尤其是与Gemini这类大模型协作让我深刻体会到未来的开发者不仅要会写代码更要懂得如何与AI“对话”用精确的指令提示词来驾驭其强大的能力。希望这个详细的拆解能给你带来启发不妨也动手“搓”一个属于自己的AI小应用吧。
返回列表