Files
n8n_Demo/web_frontend/web_result/app.js

273 lines
10 KiB
JavaScript
Raw Normal View History

const express = require('express');
const path = require('path');
const fs = require('fs');
const yaml = require('js-yaml');
// 加载路由配置
function loadRoutes() {
try {
const fileContents = fs.readFileSync('routes.yaml', 'utf8');
return yaml.load(fileContents);
} catch (e) {
console.error('加载路由配置失败:', e);
process.exit(1);
}
}
const config = loadRoutes();
const app = express();
const PORT = config.server.port || 4155;
// 静态文件服务
app.use('/css', express.static('css'));
app.use('/js', express.static('js'));
app.use('/data', express.static('data'));
app.use('/order-classes', express.static('order-classes'));
// 日志中间件
app.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
next();
});
// 主路由 - 显示订单班选择页面
app.get('/', (req, res) => {
const orderClass = req.query.class;
if (orderClass) {
// 如果指定了订单班,重定向到对应路由
res.redirect(`/order-class/${orderClass}`);
} else {
// 显示选择页面
res.send(generateIndexPage());
}
});
// 订单班路由
app.get('/order-class/:className', (req, res) => {
const className = req.params.className;
const classConfig = config.order_classes[className];
if (!classConfig) {
res.status(404).send(generate404Page(className));
return;
}
// 如果订单班已完成,返回其页面
if (classConfig.status === 'completed') {
const filePath = path.join(__dirname, classConfig.path, classConfig.entry);
if (fs.existsSync(filePath)) {
// 读取文件并修改相对路径
let html = fs.readFileSync(filePath, 'utf8');
// 修正资源路径
html = html.replace(/href="css\//g, 'href="/css/');
html = html.replace(/src="js\//g, 'src="/js/');
html = html.replace(/href="pages\//g, `href="${classConfig.path}`);
html = html.replace(/src="\/data\//g, 'src="/data/');
html = html.replace(/href="\/pages\//g, `href="${classConfig.path}`);
res.send(html);
} else {
res.send(generateComingSoonPage(classConfig));
}
} else {
res.send(generateComingSoonPage(classConfig));
}
});
// 处理订单班内部页面如文旅的overview.html等
app.get('/order-classes/:className/:page', (req, res) => {
const { className, page } = req.params;
const filePath = path.join(__dirname, 'order-classes', className, page);
if (fs.existsSync(filePath)) {
let html = fs.readFileSync(filePath, 'utf8');
// 修正资源路径
html = html.replace(/href="\.\.\/css\//g, 'href="/css/');
html = html.replace(/src="\.\.\/js\//g, 'src="/js/');
html = html.replace(/src="\/data\//g, 'src="/data/');
res.send(html);
} else {
res.status(404).send(generate404Page(`${className}/${page}`));
}
});
// 生成首页(选择页面)
function generateIndexPage() {
const orderClasses = Object.entries(config.order_classes);
const completedClasses = orderClasses.filter(([_, c]) => c.status === 'completed');
const pendingClasses = orderClasses.filter(([_, c]) => c.status === 'pending');
return `<!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>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
body { font-family: 'Inter', 'Noto Sans SC', sans-serif; }
.order-card {
transition: all 0.3s ease;
cursor: pointer;
}
.order-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 30px rgba(0,0,0,0.15);
}
.gradient-bg {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
</style>
</head>
<body class="bg-gray-50">
<div class="gradient-bg text-white py-12">
<div class="container mx-auto px-4 text-center">
<h1 class="text-4xl font-bold mb-4">订单班AI生成方案展示系统</h1>
<p class="text-xl opacity-90">基于多Agent协作的智能方案生成平台</p>
</div>
</div>
<div class="container mx-auto px-4 py-12">
<h2 class="text-2xl font-bold mb-6">已完成的订单班方案</h2>
<div class="grid md:grid-cols-3 lg:grid-cols-4 gap-6 mb-12">
${completedClasses.map(([key, config]) => `
<div class="order-card bg-white rounded-lg p-6 shadow-md" onclick="location.href='/order-class/${key}'">
<div class="text-3xl mb-3">${getClassIcon(key)}</div>
<h3 class="font-bold text-lg mb-2">${config.name}</h3>
<p class="text-sm text-gray-600 mb-3">${config.description}</p>
<div class="text-sm text-gray-500">
<i class="fas fa-users"></i> ${config.agents.length || 0} AI
</div>
<div class="mt-4 text-blue-600 font-semibold">
查看方案 <i class="fas fa-arrow-right"></i>
</div>
</div>
`).join('')}
</div>
<h2 class="text-2xl font-bold mb-6 text-gray-500">即将推出</h2>
<div class="grid md:grid-cols-3 lg:grid-cols-4 gap-6">
${pendingClasses.map(([key, config]) => `
<div class="bg-gray-100 rounded-lg p-6 opacity-60">
<div class="text-3xl mb-3 text-gray-400">${getClassIcon(key)}</div>
<h3 class="font-bold text-lg mb-2 text-gray-500">${config.name}</h3>
<p class="text-sm text-gray-400">${config.description}</p>
<div class="mt-4 text-gray-400">
开发中...
</div>
</div>
`).join('')}
</div>
</div>
<script>
// 可以添加一些交互效果
</script>
</body>
</html>`;
}
// 生成404页面
function generate404Page(resource) {
return `<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>页面未找到</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 flex items-center justify-center min-h-screen">
<div class="text-center">
<h1 class="text-6xl font-bold text-gray-300 mb-4">404</h1>
<p class="text-xl text-gray-600 mb-2">页面未找到</p>
<p class="text-gray-500 mb-6">资源 "${resource}" 不存在</p>
<a href="/" class="bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700">
返回首页
</a>
</div>
</body>
</html>`;
}
// 生成即将推出页面
function generateComingSoonPage(classConfig) {
return `<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${classConfig.name} - 即将推出</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gradient-to-br from-purple-600 to-blue-600 text-white min-h-screen flex items-center justify-center">
<div class="text-center">
<div class="text-6xl mb-6">${getClassIcon(classConfig.name)}</div>
<h1 class="text-4xl font-bold mb-4">${classConfig.name}</h1>
<p class="text-xl mb-2">${classConfig.title}</p>
<p class="opacity-80 mb-8">${classConfig.description}</p>
<div class="bg-white/20 backdrop-blur rounded-lg p-6 max-w-md mx-auto">
<p class="text-lg font-semibold mb-2">🚀 正在开发中</p>
<p>我们的AI专家团队正在为您准备专业的解决方案</p>
</div>
<a href="/" class="mt-8 inline-block bg-white text-purple-600 px-6 py-3 rounded-lg hover:bg-gray-100">
返回首页
</a>
</div>
</body>
</html>`;
}
// 获取订单班图标
function getClassIcon(key) {
const icons = {
'wenlu': '🚗',
'food': '🍽️',
'caijing': '💰',
'jiankang': '🏥',
'huagong': '⚗️',
'huanbao': '🌱',
'jiaotong': '🚚',
'nengyuan': '⚡',
'shijue': '🎨',
'tumu': '🏗️',
'zhineng-dev': '💻',
'zhineng-mfg': '🏭'
};
return icons[key] || '📦';
}
// 启动服务器
app.listen(PORT, () => {
console.log(`
订单班AI生成方案展示系统 - 服务器已启动
访问地址:
http://localhost:${PORT} ║
路由示例:
首页: http://localhost:${PORT}/ ║
文旅: http://localhost:${PORT}/order-class/wenlu ║
食品: http://localhost:${PORT}/order-class/food ║
快捷访问:
http://localhost:${PORT}/?class=wenlu ║
http://localhost:${PORT}/?class=food ║
`);
});
// 优雅关闭
process.on('SIGINT', () => {
console.log('\n正在关闭服务器...');
process.exit(0);
});