Files
Agent-n8n/web_frontend/web_result/app.js
Yep_Q 4287a35826 feat: 完善订单班路由系统,支持全部12个订单班
详细说明:
- 更新routes.yaml配置,将所有订单班状态设为completed
- 重构app.js静态文件路由,使用循环简化代码
- 更新订单班图标映射,匹配实际目录名称
- 修复订单班路由跳转,支持以下订单班:
  * wenlu(文旅) - 会展策划
  * food(食品) - 轻食经营
  * finance(财经商贸) - 电商运营
  * health(大健康) - 智慧养老
  * chemical(化工) - 废水处理
  * environmental(环保) - 水质监测
  * transportation(交通物流) - 冷链物流
  * energy(能源) - 光伏发电
  * visual-design(视觉设计) - 宣传片策划
  * civil(土木) - 室内设计
  * developer(智能开发) - AI检测
  * manufacturing(智能制造) - 系统集成

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-09 10:06:58 +08:00

299 lines
11 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.

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'));
// 为所有订单班提供独立的静态文件服务
const orderClassDirs = ['wenlu', 'food', 'finance', 'health', 'chemical', 'environmental',
'transportation', 'energy', 'visual-design', 'civil', 'developer', 'manufacturing'];
orderClassDirs.forEach(dir => {
app.use(`/order-class/${dir}/css`, express.static(`order-classes/${dir}/css`));
app.use(`/order-class/${dir}/js`, express.static(`order-classes/${dir}/js`));
app.use(`/order-class/${dir}/data`, express.static(`order-classes/${dir}/data`));
app.use(`/order-class/${dir}/images`, express.static(`order-classes/${dir}/images`));
app.use(`/order-class/${dir}/agent-avatars`, express.static(`order-classes/${dir}/agent-avatars`));
});
// 日志中间件
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());
}
});
// 处理 /order-class/*.html 形式的请求wenlu 子页面)- 必须放在前面
app.get('/order-class/:page', (req, res, next) => {
const page = req.params.page;
// 只处理 .html 文件
if (!page.endsWith('.html')) {
// 如果不是 .html 文件,继续下一个路由
next();
return;
}
const filePath = path.join(__dirname, 'order-classes', 'wenlu', page);
if (fs.existsSync(filePath)) {
let html = fs.readFileSync(filePath, 'utf8');
res.send(html);
} else {
res.status(404).send(generate404Page(page));
}
});
// 订单班路由
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');
// 保持相对路径,让浏览器自己解析
// 不需要修改路径,因为我们已经设置了静态文件服务
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');
// 保持相对路径不变
res.send(html);
} else {
res.status(404).send(generate404Page(`${className}/${page}`));
}
});
// 已删除 /order-class/pages/: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': '🍽️',
'finance': '💰',
'health': '🏥',
'chemical': '⚗️',
'environmental': '🌱',
'transportation': '🚚',
'energy': '⚡',
'visual-design': '🎨',
'civil': '🏗️',
'developer': '💻',
'manufacturing': '🏭'
};
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);
});