feat(宏观): ifinance 分类动态挂载为宏观 tab, 报警迁入监控, 下线油价/本地经济数据/策略研究
Docker Build and Push / build-image (push) Successful in 2m37s
Docker Build and Push / build-image (push) Successful in 2m37s
- 宏观只保留本地 新闻/经济文章, 外接 ifinance categories[] 动态成为 tab (纯前端直连, CORS/_headers, https) - 报警从宏观迁到监控第 4 个 tab (保留 Alert 模块, 供未来新增报警源) - 彻底删除油价/经济数据/策略研究: 前端组件+api、后端 apizero/data 路由、cron、fetchers、种子数据 - 新增迁移 DROP Indicator/IndicatorPoint/Strategy/OilPriceHistory; 重新生成 Prisma Client - CSP 放开 *.honor3.com (含端口通配), 避免新增子域反复重装外壳
This commit is contained in:
@@ -1,63 +0,0 @@
|
||||
// apizero 代理路由 (前端不直接调 apizero, 一律走后端, key 不外泄)
|
||||
//
|
||||
// GET /api/apizero/oil/forecast - 油价 + 预测 (实时)
|
||||
// GET /api/apizero/oil/price-all - 32 省油价
|
||||
// GET /api/apizero/oil/price?province= - 单省油价
|
||||
// GET /api/apizero/oil/schedule?year= - 某年调价日历 (按年缓存)
|
||||
//
|
||||
// 错误: apizero 错误统一包成 502 (上游错误) 或 400 (参数错误)
|
||||
import { Router } from 'express'
|
||||
import { authRequired } from '../middleware.js'
|
||||
import { ApizeroError, oil, history } from '../apizero/index.js'
|
||||
|
||||
const router = Router()
|
||||
router.use(authRequired)
|
||||
|
||||
function handleApizeroError(e, res, next) {
|
||||
if (e instanceof ApizeroError) {
|
||||
// 参数错 -> 400, 上游错 -> 502, QPS 限流 / 额度用完 -> 503
|
||||
if (e.httpStatus === 400) return res.status(400).json({ error: e.message, apizero_code: e.code })
|
||||
if (e.code === 4029 || e.code === 4030) return res.status(503).json({ error: e.message, apizero_code: e.code })
|
||||
return res.status(502).json({ error: e.message, apizero_code: e.code })
|
||||
}
|
||||
next(e)
|
||||
}
|
||||
|
||||
// 实时: 油价 + 国际原油 + 下次调价预测
|
||||
router.get('/apizero/oil/forecast', async (req, res, next) => {
|
||||
try { res.json(await oil.getForecast()) }
|
||||
catch (e) { handleApizeroError(e, res, next) }
|
||||
})
|
||||
|
||||
// 32 省油价
|
||||
router.get('/apizero/oil/price-all', async (req, res, next) => {
|
||||
try { res.json(await oil.getPriceAll()) }
|
||||
catch (e) { handleApizeroError(e, res, next) }
|
||||
})
|
||||
|
||||
// 单省油价
|
||||
router.get('/apizero/oil/price', async (req, res, next) => {
|
||||
try { res.json(await oil.getPrice(req.query.province)) }
|
||||
catch (e) { handleApizeroError(e, res, next) }
|
||||
})
|
||||
|
||||
// 调价日历 (按年缓存)
|
||||
router.get('/apizero/oil/schedule', async (req, res, next) => {
|
||||
try { res.json(await oil.getSchedule(req.query.year)) }
|
||||
catch (e) { handleApizeroError(e, res, next) }
|
||||
})
|
||||
|
||||
export default router
|
||||
|
||||
// 浙江省油价历史 (DB)
|
||||
// GET /api/apizero/oil/history?fuel=92&days=180
|
||||
// - fuel: 92 / 95 / 0 (留空 = 3 个油品都返回)
|
||||
// - days: 默认 180 (半年)
|
||||
router.get('/apizero/oil/history', async (req, res, next) => {
|
||||
try {
|
||||
const fuel = req.query.fuel ? String(req.query.fuel) : undefined
|
||||
const days = Math.max(1, Math.min(Number(req.query.days) || 180, 730))
|
||||
const items = await history.query({ fuel, days })
|
||||
res.json({ items, fuel: fuel || 'all', days })
|
||||
} catch (e) { next(e) }
|
||||
})
|
||||
+2
-31
@@ -6,36 +6,7 @@ const router = Router()
|
||||
|
||||
router.use(authRequired)
|
||||
|
||||
// 指标列表: 元数据 + 明细点, 过滤 hidden (数据与脚本保留, 仅不展示)
|
||||
router.get('/indicators', async (_req, res, next) => {
|
||||
try {
|
||||
const rows = await prisma.indicator.findMany({
|
||||
where: { hidden: false },
|
||||
include: { points: { orderBy: { period: 'asc' } } },
|
||||
orderBy: [{ groupName: 'asc' }, { name: 'asc' }],
|
||||
})
|
||||
// 组装前端友好结构: points 保持从老到新
|
||||
const indicators = rows.map((r) => ({
|
||||
id: r.id,
|
||||
name: r.name,
|
||||
groupName: r.groupName,
|
||||
title: r.title,
|
||||
unit: r.unit,
|
||||
source: r.source,
|
||||
frequency: r.frequency,
|
||||
points: r.points.map((p) => ({ period: p.period, value: p.value })),
|
||||
}))
|
||||
res.json({ indicators })
|
||||
} catch (e) { next(e) }
|
||||
})
|
||||
|
||||
router.get('/strategies', async (_req, res, next) => {
|
||||
try {
|
||||
const rows = await prisma.strategy.findMany({ orderBy: { name: 'asc' } })
|
||||
res.json({ strategies: rows })
|
||||
} catch (e) { next(e) }
|
||||
})
|
||||
|
||||
// 能繁母猪存栏 (独立抓取域, 不属于宏观「经济数据」外接模块)
|
||||
router.get('/sow', async (_req, res, next) => {
|
||||
try {
|
||||
const rows = await prisma.econ_SowInventory.findMany({ orderBy: { month: 'asc' } })
|
||||
@@ -43,4 +14,4 @@ router.get('/sow', async (_req, res, next) => {
|
||||
} catch (e) { next(e) }
|
||||
})
|
||||
|
||||
export default router
|
||||
export default router
|
||||
|
||||
Reference in New Issue
Block a user