Skip to content

Repository files navigation

基金估值看板

一个部署在 Cloudflare Workers 免费版上的个人基金看板。Worker 盘中请求新浪财经估值,晚间请求东方财富正式净值,同时负责标准化数据、分析公开持仓、缓存结果并提供 API;浏览器只请求同源 Worker,不直接访问第三方接口。

在线访问:https://found.moxiao.de5.net

盘中估值由第三方根据公开信息估算,不是基金管理人公布的正式净值;非当天数据会明确标记为历史估值。

数据源说明: 盘中估值暂时使用新浪财经公开行情地址;北京时间工作日 20:30 后,Worker 会检查东方财富公布的正式净值。两个公开地址都没有面向本项目的稳定性承诺,可能出现限流、字段调整或停止服务;前端不会直接请求第三方接口。

当前临时接口

Worker 端暂时请求:

GET https://hq.sinajs.cn/list=fu_001180,fu_161116
Referer: https://finance.sina.com.cn/

项目配置使用批量占位符:

https://hq.sinajs.cn/list={symbols}

{symbols} 会在 Worker 内转换为 fu_基金代码 列表。新浪返回的是 GBK 编码的 JavaScript 变量文本,不是 JSON;适配器只提取已校验的字段,不执行返回脚本。当前使用的字段为:基金名称、估值时间、估算净值、参考净值、估算涨幅和数据日期,其余未公开字段一律忽略。

这是临时适配方案。以后更换正式供应商时,只需修改 src/providers/fundProvider.ts,前端和 /api/funds 的统一返回结构保持不变。

晚间正式净值使用:

GET https://fundmobapi.eastmoney.com/FundMNewApi/FundMNFInfo

Worker 在北京时间工作日 20:30 后才主动检查;未取得当天净值时最多每 5 分钟重试一次,取得后缓存 12 小时。正式净值失败不会影响新浪盘中估值。

功能

  • 基金配置集中在 src/config.tsFUND_LIST
  • 新浪财经接口适配器集中在 src/providers/fundProvider.ts;生产模式通过一个批量请求获取全部自选基金估值。
  • 盘中展示新浪估算涨幅和估算净值;晚间取得当天正式数据后,自动切换为东方财富正式涨跌幅和正式净值,并显示“已更新”。
  • 展开基金可以查看昨日净值、净值日期和当前数据状态。
  • 名称明确的指数、黄金等基金直接分类;名称宽泛的基金由 Worker 根据最新公开前十大持仓分析为 CPO/光通信、PCB、半导体设备、固态电池等细分主题。
  • 持仓分析结果统一缓存到 Cloudflare KV 30 天,避免不同设备各自猜测,也避免频繁请求第三方持仓接口。
  • 分类分组、分类内排名、涨幅升降序切换、名称/代码/分类搜索。
  • 单只基金失败不会影响其他基金;失败基金保留在结果中。
  • 新浪批量请求默认超时 8 秒,严格限制响应体大小并安全解析文本,不执行第三方脚本。
  • KV 快照缓存、300 秒新鲜度判断、60 秒刷新锁和旧缓存降级。
  • 每 5 分钟 Cron Trigger;仅在北京时间工作日 09:30–11:3013:00–15:00 更新。
  • 强制刷新需要 Cloudflare Secret REFRESH_TOKEN
  • 原生 HTML/CSS/JavaScript,支持手机横向滚动和浅色/深色模式。
  • 页面每 60 秒读取 Worker,网络失败时保留已展示数据。

项目结构

fund-dashboard/
├─ public/
│  ├─ index.html
│  ├─ style.css
│  ├─ app.js
│  ├─ favicon.svg
│  └─ _headers
├─ src/
│  ├─ index.ts
│  ├─ config.ts
│  ├─ types.ts
│  ├─ utils.ts
│  └─ providers/
│     ├─ fundProvider.ts
│     └─ providerTypes.ts
├─ wrangler.example.jsonc
├─ wrangler.jsonc              # 本地配置,不提交
├─ package.json
├─ tsconfig.json
├─ README.md
└─ .gitignore

环境要求

确认版本:

node --version
npm --version

安装依赖

cd fund-dashboard
npm install

复制公开配置模板:

Copy-Item wrangler.example.jsonc wrangler.jsonc

macOS/Linux:

cp wrangler.example.jsonc wrangler.jsonc

wrangler.jsonc 可能包含个人 KV ID 和自定义域名,因此已加入 .gitignore,不会上传到公开仓库。

Cloudflare 登录

npx wrangler login
npx wrangler whoami

KV 配置

项目使用绑定名 FUND_CACHE,键名如下:

fund_snapshot_latest
fund_refresh_lock

由模板复制出的 wrangler.jsonc 采用 Wrangler 自动资源配置:KV 绑定不填写 id,首次部署时 Wrangler 会自动创建并写回资源配置。

如需手动创建:

npx wrangler kv namespace create FUND_CACHE

然后将返回的 ID 填入本地 wrangler.jsonc

"kv_namespaces": [
  {
    "binding": "FUND_CACHE",
    "id": "这里填写KV ID"
  }
]

配置强制刷新 Secret

生产环境必须设置:

npx wrangler secret put REFRESH_TOKEN

命令会安全地提示输入密钥。不要把密钥写入源码、wrangler.jsonc 或前端。

本地开发可创建未提交的 .dev.vars

REFRESH_TOKEN=your-local-refresh-token

环境变量

非敏感变量在 wrangler.jsonc 中配置:

变量 默认值 说明
USE_MOCK_DATA false true 时完全使用模拟数据
FUND_API_URL https://hq.sinajs.cn/list={symbols} {symbols} 会替换为批量的 fu_基金代码
FUND_API_TIMEOUT 8000 新浪批量请求超时毫秒数,允许 1000–30000
CACHE_TTL 300 快照新鲜时间秒数,允许 60–3600
MAX_CONCURRENCY 5 为兼容旧配置保留;新浪批量模式不逐只并发请求

本地运行

实时接口模式:

npm run dev

模拟数据模式:

npm run dev:mock

通常访问:

http://localhost:8787

本地测试定时任务

npm run dev:cron

另开终端触发:

curl "http://localhost:8787/cdn-cgi/handler/scheduled?format=json"

模拟特定触发时间可传入 UTC 毫秒时间戳:

curl "http://localhost:8787/cdn-cgi/handler/scheduled?format=json&cron=*/5+*+*+*+*&time=1783906200000"

API

全部基金

GET /api/funds

分类筛选

GET /api/funds?category=指数型

搜索

GET /api/funds?keyword=黄金

支持名称、代码和分类,英文不区分大小写。

强制刷新

GET /api/funds?refresh=1&token=你的密钥

密钥只用于手动调用,不应放入前端。普通页面刷新按钮不会强制刷新第三方接口。

健康检查

GET /api/health

持仓主题分析

GET /api/fund-theme?code=017811

该接口由前端在后台按需调用,估值数据仍来自新浪。持仓来自最近一期公开披露,并非实时仓位;结果按代码缓存在 KV 中。

所有 API 使用统一响应:

{
  "success": true,
  "message": "ok",
  "data": {}
}

失败响应:

{
  "success": false,
  "message": "错误说明",
  "data": null
}

修改自选基金

编辑 src/config.ts

export const FUND_LIST = [
  { code: "000001", name: "示例基金", category: "混合型" },
  { code: "000002", name: "示例指数基金", category: "指数型" },
];

FUND_LIST 用于部署级固定基金;网页中新增的自选基金保存在当前浏览器。基金代码必须是六位数字。细分主题优先根据公开持仓自动识别,不需要手工选择。

更换第三方接口

第三方原始字段只存在于:

src/providers/fundProvider.ts
src/providers/providerTypes.ts

新浪盘中估值、东方财富正式净值和持仓分析接口都集中在 src/providers/fundProvider.ts。更换供应商时修改 URL、请求和字段映射,仍输出统一类型,前端不需要理解供应商字段。

类型检查与构建验证

npm run types
npm run typecheck
npm run check

部署到 Cloudflare

npm run deploy

部署完成后 Wrangler 会输出 workers.dev 地址。首次新增或修改 Cron Trigger 最多可能需要约 15 分钟传播。

查看日志

npx wrangler tail

日志包含更新开始、基金总数、成功/失败数量、第三方耗时、KV 写入和旧缓存使用情况,不会记录刷新密钥、Cookie 或敏感请求头。

常见错误排查

REFRESH_TOKEN 未配置

运行:

npx wrangler secret put REFRESH_TOKEN

KV 绑定不存在

确认 wrangler.jsonc 中绑定名为 FUND_CACHE。无绑定时 Worker 仍能运行,但页面访问会直接查询 Provider,且无法缓存。

新浪接口不可用、限流或返回 HTML

查看 npx wrangler tail。单只失败会显示 --,不会让整个接口失败。可将 USE_MOCK_DATA 改为 true 验证页面和部署。

页面仍显示旧数据

普通访问会优先使用 300 秒内的 KV 快照。需要立即更新时使用带 Secret 的强制刷新接口。

Cron 没有更新

Cron 只在北京时间周一至周五的交易时段请求 Provider,不处理法定节假日和调休。新增 Trigger 后也可能需要等待传播。

类型生成不同步

修改 wrangler.jsonc 后运行:

npm run types
npm run typecheck

免费额度注意事项

本项目按个人低频使用设计:静态资源优先由 Workers Static Assets 直接提供,API 才进入 Worker;新浪估值采用单次批量请求,不会为每只基金分别建立连接。持仓主题成功分析后 30 天内直接读 KV,不会随每分钟净值刷新重复分析。请关注 Cloudflare 当前免费额度、KV 写入额度和 Cron Trigger 数量。额度与规则可能调整,部署前以 Cloudflare 官方文档为准。

About

轻量级 Cloudflare Workers 基金盘中估值看板,支持本地自选、KV 缓存、Cron 更新和移动端适配。

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages