Files
SBrainCO/server/src/index.ts
T
freedakgmail d04e837d9c V3.0: 门店分级与风险等级页面、数据填充脚本、后端API
- 新增V3.0数据库表结构(12-15)和数据填充脚本(16)
- 新增后端路由: store-grade, enterprise, product, intelligence, alert, scheduler, target
- 新增前端页面: StoreGradePage, EnterprisePage, ProductLifecyclePage, IntelligencePage, AlertManagementPage, DataImportPage, SchedulerManagementPage, TargetManagementPage
- 门店分级: 自动分级算法(达成率40%+毛利率25%+会员15%+风险20%)
- 风险等级: 基于mv_store_risk_rating模型展示风险分布和原因
- 弹窗: 雷达图+详细指标+分级原因+风险原因(primary_issue)
- FilterableTable: filterOptions支持{value,label}对象格式
2026-08-05 20:09:39 +08:00

91 lines
3.2 KiB
TypeScript

import 'dotenv/config'
import express from 'express'
import cors from 'cors'
import { authMiddleware, AuthRequest } from './middleware/auth.js'
import { errorHandler, notFoundHandler } from './middleware/error.js'
import { tenantDbMiddleware } from './middleware/tenant-db.js'
import authRoutes from './routes/auth.js'
import dataRoutes from './routes/data.js'
import taskRoutes from './routes/tasks.js'
import costAnalysisRoutes from './routes/cost-analysis.js'
import storeExpenseRoutes from './routes/store-expense.js'
import smartSchedulingRoutes from './routes/smart-scheduling.js'
import situationalAwarenessRoutes from './routes/situational-awareness.js'
import analyticsEnhancedRoutes from './routes/analytics-enhanced.js'
import adminRoutes from './routes/admin.js'
import ttsRoutes from './routes/tts.js'
import targetRoutes from './routes/target.js'
import schedulerRoutes from './routes/scheduler.js'
import alertRoutes from './routes/alert.js'
import storeGradeRoutes from './routes/store-grade.js'
import productRoutes from './routes/product.js'
import enterpriseRoutes from './routes/enterprise.js'
import intelligenceRoutes from './routes/intelligence.js'
import { startScheduler } from './scheduler/index.js'
import { registerAllTaskHandlers } from './scheduler/task-handlers.js'
const app = express()
const PORT = parseInt(process.env.PORT || '3333')
app.use(cors({
origin: process.env.CLIENT_URL || true,
credentials: true,
}))
app.use(express.json())
app.get('/api/health', (req, res) => {
res.json({ success: true, data: { status: 'ok', time: new Date().toISOString() } })
})
app.use('/api/auth', authRoutes)
// admin login 不需要 auth 中间件
app.post('/api/admin/login', (req, res, next) => {
req.url = '/login'
adminRoutes(req, res, next)
})
app.use((req, res, next) => {
if (req.path === '/api/health' || req.path.startsWith('/api/auth')) {
return next()
}
authMiddleware(req as AuthRequest, res, next)
})
app.use('/api/admin', adminRoutes)
// 租户数据隔离中间件:根据 JWT 中的 tenantId 动态切换数据库连接池
app.use((req, res, next) => {
if (req.path.startsWith('/api/admin') || req.path === '/api/health' || req.path.startsWith('/api/auth')) {
return next()
}
tenantDbMiddleware(req as AuthRequest, res, next)
})
app.use('/api', dataRoutes)
app.use('/api/tasks', taskRoutes)
app.use('/api/cost-analysis', costAnalysisRoutes)
app.use('/api/store-expense', storeExpenseRoutes)
app.use('/api/smart-scheduling', smartSchedulingRoutes)
app.use('/api/situational-awareness', situationalAwarenessRoutes)
app.use('/api/analytics-enhanced', analyticsEnhancedRoutes)
app.use('/api/tts', ttsRoutes)
app.use('/api/target', targetRoutes)
app.use('/api/scheduler', schedulerRoutes)
app.use('/api/alert', alertRoutes)
app.use('/api/store-grade', storeGradeRoutes)
app.use('/api/product', productRoutes)
app.use('/api/enterprise', enterpriseRoutes)
app.use('/api/intelligence', intelligenceRoutes)
app.use(notFoundHandler)
app.use(errorHandler)
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`)
registerAllTaskHandlers()
startScheduler().catch(err => console.error('[Scheduler] Failed to start:', err))
})
export default app