feat: 重构定投评估工具并优化Cloud工具体验

- 重构市场定投评估逻辑:优先读取本地估值快照,必要时通过探针补抓海外数据,后端接口新增force参数支持强制刷新,更新前后端注释与交互文案
- 优化Cloud工具全链路:
  - 新增运营商登录页地址字段,支持一键复制账号密码并打开对应登录页
  - 缓存密钥派生结果,避免重复阻塞事件循环,提升列表加载性能
  - 完善接口错误处理,新增面板级加载失败提示与自动重试功能
  - 修复云资源代理转发时的Cookie缺失问题
  - 并行加载所有面板数据,优化首屏渲染速度
  - 新增登录按钮样式与错误提示样式
- 新增4个Cloud工具调试脚本,用于性能测试、解密审计、回归验证与加载耗时统计
- 启动定投评估工具的定时调度任务
This commit is contained in:
yangxiangyuan
2026-08-17 16:33:41 +08:00
parent 4016636153
commit e4f84caa23
10 changed files with 1149 additions and 237 deletions
+7 -4
View File
@@ -4784,10 +4784,10 @@ app.get('/api/markets/weekly_report', async (req, res) => {
}
})
// 建行定投评估:按需抓取四大指数 PE-TTM 与近10年分位(点击页面按钮触发,无定时任务)
// 建行定投评估:A股按需评估;海外部分优先读取本地快照,必要时通过美西探针补抓并持久化
app.get('/api/markets/dip_eval', async (req, res) => {
try {
const payload = await marketsDipEval.getDipEvalReport()
const payload = await marketsDipEval.getDipEvalReport({ force: String(req.query.force || '') === '1' })
// 统一 200 + ok 标志:整体失败时 ok=false,前端交互弹窗读取 error 文案
res.json(payload || { ok: false, error: '评估失败' })
} catch (e) {
@@ -5626,7 +5626,7 @@ app.get('/api/cloud/balance_alerts', (req, res) => {
app.get('/api/cloud/balance_alerts/status', (req, res) => {
;(async () => {
try {
const forwarded = await proxyCloudBalanceAutomationStatus('/api/cloud/balance_alerts/status')
const forwarded = await proxyCloudBalanceAutomationStatus('/api/cloud/balance_alerts/status', req)
if (forwarded) return res.status(forwarded.status).json(forwarded.body)
res.json({ ok: true, data: cloudBalanceWatch.getStatus() })
} catch (e) { res.status(500).json({ ok: false, error: String(e.message || e) }) }
@@ -5665,13 +5665,15 @@ const proxyCloudBalanceAutomationRequest = async (req, routePath) => {
})
}
}
const proxyCloudBalanceAutomationStatus = async routePath => {
const proxyCloudBalanceAutomationStatus = async (routePath, req) => {
const cfg = cloudBalanceWatch.readConfig()
const currentPort = Number(process.env.PORT || '8976') || 8976
const automationPort = Number(cfg.automation_port || 8977) || 8977
if (currentPort === automationPort) return null
const url = `http://127.0.0.1:${automationPort}${routePath}`
// 必须转发 Cookie,否则 8977 的 /api/cloud 守卫会返回 401
const proxied = await axios.get(url, {
headers: { Cookie: (req && req.headers && req.headers.cookie) || '' },
timeout: 15000,
validateStatus: () => true
})
@@ -7376,6 +7378,7 @@ if (currentPort === marketsAutomationPort) {
securityCalendar.startScheduler()
securityCalendarBridge.startScheduler(securityCalendar)
marketsWeeklyReport.startScheduler()
marketsDipEval.startScheduler()
globalNews.startScheduler()
app.use('/api/yuanzhupai', (req, res, next) => {