Initial commit: ERP system with advance verification fixes

This commit is contained in:
System Administrator
2026-03-25 23:55:36 +07:00
commit 563ca12d76
5920 changed files with 828689 additions and 0 deletions
@@ -0,0 +1,436 @@
const express = require('express');
const cors = require('cors');
const path = require('path');
const db = require('./db');
// 导入路由模块
const financeRouter = require('./finance-api');
const app = express();
const PORT = process.env.PORT || 5000;
// 中间件
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// 静态文件服务 - 前端应用
app.use('/app', express.static(path.join(__dirname, '../frontend/dist')));
// 健康检查
app.get('/health', async (req, res) => {
try {
// 测试数据库连接
await db.query('SELECT 1');
res.json({
status: 'healthy',
service: 'company-finance-system',
timestamp: new Date().toISOString(),
version: '1.0.0',
database: 'connected',
endpoints: {
frontend: '/app/index.html',
api: '/api/*',
finance: '/api/finance/*',
test: '/test'
}
});
} catch (error) {
res.status(500).json({
status: 'unhealthy',
service: 'company-finance-system',
timestamp: new Date().toISOString(),
database: 'disconnected',
error: error.message
});
}
});
// API路由
app.use('/api/finance', financeRouter);
// 客户管理API
app.get('/api/customers', async (req, res) => {
try {
const result = await db.query(`
SELECT
c.*,
COUNT(ct.contact_id) as contact_count
FROM customers c
LEFT JOIN contacts ct ON c.customer_id = ct.customer_id
GROUP BY c.customer_id
ORDER BY c.created_at DESC
`);
res.json({
success: true,
data: result.rows,
count: result.rows.length
});
} catch (error) {
console.error('获取客户失败:', error);
res.status(500).json({
success: false,
message: '获取客户失败',
error: error.message
});
}
});
// 供应商管理API
app.get('/api/suppliers', async (req, res) => {
try {
const result = await db.query(`
SELECT
s.*,
COUNT(ct.contact_id) as contact_count
FROM suppliers s
LEFT JOIN contacts ct ON s.supplier_id = ct.supplier_id
GROUP BY s.supplier_id
ORDER BY s.created_at DESC
`);
res.json({
success: true,
data: result.rows,
count: result.rows.length
});
} catch (error) {
console.error('获取供应商失败:', error);
res.status(500).json({
success: false,
message: '获取供应商失败',
error: error.message
});
}
});
// 项目管理API
app.get('/api/projects', async (req, res) => {
try {
const result = await db.query(`
SELECT
p.*,
c.company_name as customer_name,
s.company_name as supplier_name,
COUNT(pn.node_id) as payment_node_count,
SUM(pn.amount) as total_amount
FROM projects p
LEFT JOIN customers c ON p.customer_id = c.customer_id
LEFT JOIN suppliers s ON p.supplier_id = s.supplier_id
LEFT JOIN payment_nodes pn ON p.project_id = pn.project_id
GROUP BY p.project_id, c.company_name, s.company_name
ORDER BY p.created_at DESC
`);
res.json({
success: true,
data: result.rows,
count: result.rows.length
});
} catch (error) {
console.error('获取项目失败:', error);
res.status(500).json({
success: false,
message: '获取项目失败',
error: error.message
});
}
});
// 测试数据API(用于演示)
app.get('/api/test-data', async (req, res) => {
try {
// 获取各种统计数据
const [customers, suppliers, projects, paymentNodes, paymentRecords] = await Promise.all([
db.query('SELECT COUNT(*) as count FROM customers'),
db.query('SELECT COUNT(*) as count FROM suppliers'),
db.query('SELECT COUNT(*) as count FROM projects'),
db.query('SELECT COUNT(*) as count FROM payment_nodes'),
db.query('SELECT COUNT(*) as count FROM payment_records')
]);
res.json({
success: true,
data: {
customers: customers.rows[0].count,
suppliers: suppliers.rows[0].count,
projects: projects.rows[0].count,
paymentNodes: paymentNodes.rows[0].count,
paymentRecords: paymentRecords.rows[0].count,
timestamp: new Date().toISOString()
}
});
} catch (error) {
res.json({
success: false,
message: '获取测试数据失败',
error: error.message
});
}
});
// 测试页面
app.get('/test', (req, res) => {
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>公司财务管理系统 - 生产环境测试</title>
<meta charset="utf-8">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; }
.container { max-width: 1200px; margin: 0 auto; padding: 40px 20px; }
.header { text-align: center; margin-bottom: 40px; color: white; }
h1 { font-size: 48px; margin-bottom: 10px; text-shadow: 0 2px 10px rgba(0,0,0,0.2); }
.subtitle { font-size: 18px; opacity: 0.9; }
.dashboard { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-bottom: 40px; }
.card { background: white; border-radius: 15px; padding: 30px; box-shadow: 0 10px 30px rgba(0,0,0,0.1); transition: transform 0.3s; }
.card:hover { transform: translateY(-5px); }
.card h2 { color: #333; margin-bottom: 20px; border-bottom: 2px solid #667eea; padding-bottom: 10px; }
.btn { display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 12px 24px; border-radius: 8px; text-decoration: none; margin: 5px; border: none; cursor: pointer; font-weight: 500; }
.btn:hover { opacity: 0.9; }
.btn-secondary { background: #4CAF50; }
.status { padding: 10px; border-radius: 8px; margin: 10px 0; }
.status-ok { background: #e8f5e9; border: 1px solid #4CAF50; color: #2e7d32; }
.status-error { background: #ffebee; border: 1px solid #f44336; color: #c62828; }
.system-info { background: rgba(255,255,255,0.1); backdrop-filter: blur(10px); border-radius: 15px; padding: 30px; margin-top: 40px; color: white; }
.info-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-top: 20px; }
.info-item { padding: 15px; background: rgba(255,255,255,0.1); border-radius: 8px; }
.quick-links { display: flex; flex-wrap: wrap; gap: 10px; margin: 20px 0; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🏢 公司财务管理系统</h1>
<div class="subtitle">生产环境 v1.0.0 | 服务器: 43.161.248.209:${PORT}</div>
</div>
<div class="dashboard">
<div class="card">
<h2>🚀 立即使用</h2>
<p>访问完整的前端应用程序,开始管理您的财务。</p>
<div class="quick-links">
<a href="/app/index.html" class="btn">进入系统</a>
<a href="/health" class="btn btn-secondary">健康检查</a>
</div>
</div>
<div class="card">
<h2>🔧 系统测试</h2>
<p>测试各个组件是否正常工作。</p>
<div class="quick-links">
<button class="btn" onclick="testAPI()">测试API</button>
<button class="btn" onclick="testDatabase()">测试数据库</button>
<button class="btn" onclick="testFrontend()">测试前端</button>
</div>
<div id="test-results"></div>
</div>
<div class="card">
<h2>📊 系统状态</h2>
<div id="system-status">检查中...</div>
<div class="quick-links">
<a href="/api/test-data" class="btn" target="_blank">查看数据统计</a>
<a href="/api/customers" class="btn" target="_blank">客户API</a>
</div>
</div>
</div>
<div class="system-info">
<h2>📋 系统信息</h2>
<div class="info-grid">
<div class="info-item">
<div style="font-size: 12px; opacity: 0.8;">服务器IP</div>
<div style="font-size: 18px; font-weight: bold;">43.161.248.209</div>
</div>
<div class="info-item">
<div style="font-size: 12px; opacity: 0.8;">服务端口</div>
<div style="font-size: 18px; font-weight: bold;">${PORT}</div>
</div>
<div class="info-item">
<div style="font-size: 12px; opacity: 0.8;">数据库</div>
<div style="font-size: 18px; font-weight: bold;">PostgreSQL</div>
</div>
<div class="info-item">
<div style="font-size: 12px; opacity: 0.8;">前端技术</div>
<div style="font-size: 18px; font-weight: bold;">React + Ant Design</div>
</div>
</div>
<div style="margin-top: 30px;">
<h3>🔗 快速链接</h3>
<div class="quick-links">
<a href="/api/finance/payment-nodes" class="btn" target="_blank">付款节点API</a>
<a href="/api/finance/payment-records" class="btn" target="_blank">付款记录API</a>
<a href="/api/finance/exchange-rates" class="btn" target="_blank">汇率API</a>
<a href="/api/finance/finance-stats" class="btn" target="_blank">财务统计</a>
</div>
</div>
</div>
</div>
<script>
// 测试函数
async function testAPI() {
const results = document.getElementById('test-results');
results.innerHTML = '<div class="status">测试API连接...</div>';
try {
const response = await fetch('/health');
const data = await response.json();
results.innerHTML = \`
<div class="status status-ok">
✅ API正常<br>
服务: \${data.service}<br>
数据库: \${data.database}<br>
时间: \${new Date(data.timestamp).toLocaleString()}
</div>
\`;
} catch (error) {
results.innerHTML = \`<div class="status status-error">❌ API连接失败: \${error.message}</div>\`;
}
}
async function testDatabase() {
const results = document.getElementById('test-results');
results.innerHTML = '<div class="status">测试数据库连接...</div>';
try {
const response = await fetch('/api/test-data');
const data = await response.json();
if (data.success) {
results.innerHTML = \`
<div class="status status-ok">
✅ 数据库连接正常<br>
客户数: \${data.data.customers}<br>
供应商数: \${data.data.suppliers}<br>
项目数: \${data.data.projects}
</div>
\`;
} else {
results.innerHTML = \`<div class="status status-error">⚠️ 数据库连接可能有问题</div>\`;
}
} catch (error) {
results.innerHTML = \`<div class="status status-error">❌ 数据库测试失败: \${error.message}</div>\`;
}
}
async function testFrontend() {
const results = document.getElementById('test-results');
results.innerHTML = '<div class="status">测试前端访问...</div>';
try {
const response = await fetch('/app/index.html');
if (response.ok) {
results.innerHTML = '<div class="status status-ok">✅ 前端页面可正常访问</div>';
} else {
results.innerHTML = '<div class="status status-error">❌ 前端页面访问失败</div>';
}
} catch (error) {
results.innerHTML = \`<div class="status status-error">❌ 前端测试失败: \${error.message}</div>\`;
}
}
// 检查系统状态
async function checkSystemStatus() {
const statusEl = document.getElementById('system-status');
try {
const response = await fetch('/health');
const data = await response.json();
if (data.status === 'healthy') {
statusEl.innerHTML = \`
<div class="status status-ok">
✅ 系统运行正常<br>
🔗 <a href="/app/index.html" style="color: #2e7d32;">点击进入系统</a>
</div>
\`;
} else {
statusEl.innerHTML = \`<div class="status status-error">⚠️ 系统状态异常: \${data.status}</div>\`;
}
} catch (error) {
statusEl.innerHTML = \`<div class="status status-error">❌ 无法获取系统状态: \${error.message}</div>\`;
}
}
// 页面加载时自动检查
window.onload = function() {
checkSystemStatus();
testAPI();
};
</script>
</body>
</html>
`);
});
// 默认路由重定向到前端
app.get('/', (req, res) => {
res.redirect('/app/index.html');
});
// 404处理
app.use((req, res) => {
res.status(404).send(`
<!DOCTYPE html>
<html>
<head><title>页面未找到</title><meta charset="utf-8"></head>
<body style="font-family: Arial; text-align: center; padding: 50px;">
<h1>404 - 页面未找到</h1>
<p>您访问的页面不存在。</p>
<p><a href="/app/index.html">返回首页</a> | <a href="/test">测试页面</a></p>
</body>
</html>
`);
});
// 错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({
success: false,
message: '服务器内部错误',
error: process.env.NODE_ENV === 'development' ? err.message : undefined
});
});
// 启动服务器
const server = app.listen(PORT, '0.0.0.0', () => {
console.log(`
🚀 公司财务管理系统 - 生产服务器
====================================
📍 服务器地址: http://0.0.0.0:${PORT}
🌐 外部访问: http://43.161.248.209:${PORT}
🔗 重要链接:
- 前端应用: http://43.161.248.209:${PORT}/app/index.html
- 测试页面: http://43.161.248.209:${PORT}/test
- 健康检查: http://43.161.248.209:${PORT}/health
- API文档: http://43.161.248.209:${PORT}/api/*
📊 已启用的模块:
✅ 财务模块 (付款节点、付款记录、汇率)
✅ 客户管理
✅ 供应商管理
✅ 项目管理
✅ 静态文件服务
⏰ 启动时间: ${new Date().toISOString()}
====================================
`);
});
// 优雅关闭
process.on('SIGTERM', () => {
console.log('收到SIGTERM信号,正在关闭服务器...');
server.close(() => {
console.log('服务器已关闭');
process.exit(0);
});
});