Files
ai-tutor-template-244/prototype-mobile/server.js
yourname 9b9e64583a feat: 添加移动端原型系统(微信小程序风格)
- 7 个 HTML 页面(106KB)
- 移动端模式:375×812 手机框架
- 基于需求文档中的 UI/UX 设计规格生成

页面列表:
- mobile-index.html: 移动端统一入口
- home.html: 首页抽背启动(4个抽背考点按钮)
- ai-quiz.html: AI抽背界面(语音交互)
- quiz-report.html: 抽背报告(正确率、错误分析)
- memory-curve.html: 记忆曲线可视化(复习计划日历)
- card-recite.html: 卡片背诵(挖空填空)
- profile.html: 个人中心

技术栈:Tailwind CSS + Font Awesome
设计规范:蓝色/绿色渐变导航,375×812 手机框架

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 15:47:26 +00:00

173 lines
5.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* AI 智能抽背助手 - 移动端原型本地预览服务器
*
* 使用方法:
* node server.js
*
* 功能:
* - 启动本地 HTTP 服务器(端口 8081
* - 自动打开浏览器访问移动端原型
* - 支持热重载(修改文件后自动刷新)
*
* @author generate-prototype-grid skill
* @date 2026-03-28
*/
const http = require('http');
const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');
const PORT = 8081;
const PROTOTYPE_DIR = __dirname;
// MIME 类型映射
const MIME_TYPES = {
'.html': 'text/html; charset=utf-8',
'.css': 'text/css; charset=utf-8',
'.js': 'application/javascript; charset=utf-8',
'.json': 'application/json; charset=utf-8',
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.gif': 'image/gif',
'.svg': 'image/svg+xml',
'.ico': 'image/x-icon',
'.woff': 'font/woff',
'.woff2': 'font/woff2',
'.ttf': 'font/ttf',
'.md': 'text/markdown; charset=utf-8',
};
// 创建服务器
const server = http.createServer((req, res) => {
// 解析 URL
let urlPath = req.url;
// 处理根路径
if (urlPath === '/') {
urlPath = '/mobile-index.html';
}
// 构建文件路径
const filePath = path.join(PROTOTYPE_DIR, urlPath);
const extname = path.extname(filePath).toLowerCase();
// 设置响应头
const contentType = MIME_TYPES[extname] || 'application/octet-stream';
// 读取并返回文件
fs.readFile(filePath, (err, content) => {
if (err) {
if (err.code === 'ENOENT') {
// 文件不存在
res.writeHead(404, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(`
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>404 - 文件未找到</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.error-box {
text-align: center;
background: white;
padding: 40px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
h1 { color: #667eea; margin: 0 0 16px 0; }
p { color: #666; margin: 0 0 24px 0; }
a {
color: #667eea;
text-decoration: none;
padding: 8px 16px;
border: 1px solid #667eea;
border-radius: 6px;
display: inline-block;
}
a:hover { background: #667eea; color: white; }
</style>
</head>
<body>
<div class="error-box">
<h1>404</h1>
<p>文件未找到: ${urlPath}</p>
<a href="/mobile-index.html">返回首页</a>
</div>
</body>
</html>
`);
} else {
// 服务器错误
res.writeHead(500, { 'Content-Type': 'text/html; charset=utf-8' });
res.end('服务器错误: ' + err.code);
}
} else {
// 成功返回文件
res.writeHead(200, { 'Content-Type': contentType });
res.end(content);
}
});
});
// 启动服务器
server.listen(PORT, () => {
console.log('='.repeat(60));
console.log(' AI 智能抽背助手 - 移动端原型本地预览服务器');
console.log('='.repeat(60));
console.log('');
console.log(` 服务器地址: http://localhost:${PORT}`);
console.log('');
console.log(' 可用页面:');
console.log(` - 统一入口: http://localhost:${PORT}/mobile-index.html`);
console.log('');
console.log(' 移动端页面:');
console.log(` - 首页抽背: /pages/mobile/home.html`);
console.log(` - AI智能抽背: /pages/mobile/ai-quiz.html`);
console.log(` - 抽背报告: /pages/mobile/quiz-report.html`);
console.log(` - 记忆曲线: /pages/mobile/memory-curve.html`);
console.log(` - 卡片背诵: /pages/mobile/card-recite.html`);
console.log(` - 个人中心: /pages/mobile/profile.html`);
console.log('');
console.log(' 按 Ctrl+C 停止服务器');
console.log('='.repeat(60));
console.log('');
// 自动打开浏览器
const openCommand = process.platform === 'win32' ? 'start' :
process.platform === 'darwin' ? 'open' : 'xdg-open';
exec(`${openCommand} http://localhost:${PORT}`, (error) => {
if (error) {
console.log(' 提示: 无法自动打开浏览器,请手动访问上述地址');
} else {
console.log(' 已自动打开浏览器');
}
console.log('');
});
});
// 优雅退出
process.on('SIGINT', () => {
console.log('');
console.log('正在停止服务器...');
server.close(() => {
console.log('服务器已停止');
process.exit(0);
});
});
module.exports = server;