All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
后端 - 新建 bi_ele_charge_record 表(首次访问自动 CREATE TABLE IF NOT EXISTS) 字段含订单编号(UNIQUE)、电站、时段、电量/费用、车牌/判定车牌、内外部分类、原始 JSON、批次号 - POST /api/ele/import:multipart 上传 xlsx,识别表头自动定位, 文件内 + 数据库双重去重(INSERT IGNORE on UNIQUE order_no) 上传时按 plate/judged_plate 在 tab_truck 中匹配,命中=internal、未命中但有牌=external、无牌=unknown - GET /api/ele/list 分页 + kind/batch/search 过滤 - GET /api/ele/batches 批次汇总(数量、内/外/未知拆分、电量/费用合计) - GET /api/ele/aggregate 全量与近 30 日按日 × 分类聚合 前端 - /ele/import 路径直接渲染 EleImportPage,主导航不显示,需手动输入 URL - 拖拽/点击上传,结果卡展示解析/新增/重复/分类 - KPI 8 卡:总数、内/外/未知记录、累计电量与费用、内/外电量 - 批次列表(点击筛选)+ 最新记录表(kind 切换 + 关键字搜索) - 上传后自动 reload 全部数据 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
46 lines
1.6 KiB
TypeScript
46 lines
1.6 KiB
TypeScript
import { serve } from '@hono/node-server';
|
|
import { serveStatic } from '@hono/node-server/serve-static';
|
|
import { Hono } from 'hono';
|
|
import { cors } from 'hono/cors';
|
|
import dotenv from 'dotenv';
|
|
import vehiclesRouter from './routes/vehicles.js';
|
|
import mileageRouter from './routes/mileage/index.js';
|
|
import schedulingRouter from './routes/scheduling/index.js';
|
|
import energyRouter from './routes/energy/index.js';
|
|
import eleRouter from './routes/ele/index.js';
|
|
import { ensureSchedulingTables } from './routes/scheduling/db-schema.js';
|
|
import authRouter from './auth/login.js';
|
|
import { authMiddleware } from './auth/middleware.js';
|
|
|
|
dotenv.config();
|
|
|
|
const app = new Hono();
|
|
|
|
app.use('/api/*', cors());
|
|
|
|
// Auth 路由(不需要中间件)
|
|
app.route('/api/auth', authRouter);
|
|
|
|
// Auth 中间件(保护后续所有 /api/* 路由)
|
|
app.use('/api/*', authMiddleware);
|
|
|
|
app.route('/api/vehicles', vehiclesRouter);
|
|
app.route('/api/mileage', mileageRouter);
|
|
app.route('/api/scheduling', schedulingRouter);
|
|
app.route('/api/energy', energyRouter);
|
|
app.route('/api/ele', eleRouter);
|
|
|
|
app.get('/api/health', (c) => c.json({ status: 'ok', time: new Date().toISOString() }));
|
|
|
|
// Serve static files in production
|
|
app.use('/*', serveStatic({ root: './dist' }));
|
|
app.use('/*', serveStatic({ root: './dist', path: 'index.html' }));
|
|
|
|
const port = Number(process.env.SERVER_PORT) || 3001;
|
|
|
|
console.log(`Server starting on port ${port}...`);
|
|
ensureSchedulingTables().catch(e => console.error('scheduling bootstrap error:', e));
|
|
serve({ fetch: app.fetch, port }, () => {
|
|
console.log(`Server running at http://localhost:${port}`);
|
|
});
|