详细说明: - 修复getProjectInfo函数中seq.agent()的类型错误 - 添加兼容性处理,支持函数和对象两种数据格式 - 解决选择订单班后点击按钮导致页面崩溃的问题 - 修改文件: WorkflowPageV4.tsx (第934行) - 影响模块: ResultModal数据显示系统 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
310 lines
12 KiB
JavaScript
310 lines
12 KiB
JavaScript
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('/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/wenlu/*.html 形式的请求
|
||
app.get('/order-class/wenlu/:page', (req, res) => {
|
||
const page = req.params.page;
|
||
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(`wenlu/${page}`));
|
||
}
|
||
});
|
||
|
||
// 处理 /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);
|
||
}); |