一个部署在 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.ts的FUND_LIST。 - 新浪财经接口适配器集中在
src/providers/fundProvider.ts;生产模式通过一个批量请求获取全部自选基金估值。 - 盘中展示新浪估算涨幅和估算净值;晚间取得当天正式数据后,自动切换为东方财富正式涨跌幅和正式净值,并显示“已更新”。
- 展开基金可以查看昨日净值、净值日期和当前数据状态。
- 名称明确的指数、黄金等基金直接分类;名称宽泛的基金由 Worker 根据最新公开前十大持仓分析为 CPO/光通信、PCB、半导体设备、固态电池等细分主题。
- 持仓分析结果统一缓存到 Cloudflare KV 30 天,避免不同设备各自猜测,也避免频繁请求第三方持仓接口。
- 分类分组、分类内排名、涨幅升降序切换、名称/代码/分类搜索。
- 单只基金失败不会影响其他基金;失败基金保留在结果中。
- 新浪批量请求默认超时 8 秒,严格限制响应体大小并安全解析文本,不执行第三方脚本。
- KV 快照缓存、300 秒新鲜度判断、60 秒刷新锁和旧缓存降级。
- 每 5 分钟 Cron Trigger;仅在北京时间工作日
09:30–11:30、13: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.js 20 或更高版本:https://nodejs.org/
- npm
- Cloudflare 账号
确认版本:
node --version
npm --versioncd fund-dashboard
npm install复制公开配置模板:
Copy-Item wrangler.example.jsonc wrangler.jsoncmacOS/Linux:
cp wrangler.example.jsonc wrangler.jsoncwrangler.jsonc 可能包含个人 KV ID 和自定义域名,因此已加入 .gitignore,不会上传到公开仓库。
npx wrangler login
npx wrangler whoami项目使用绑定名 FUND_CACHE,键名如下:
fund_snapshot_latest
fund_refresh_lock
由模板复制出的 wrangler.jsonc 采用 Wrangler 自动资源配置:KV 绑定不填写 id,首次部署时 Wrangler 会自动创建并写回资源配置。
如需手动创建:
npx wrangler kv namespace create FUND_CACHE然后将返回的 ID 填入本地 wrangler.jsonc:
生产环境必须设置:
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"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 checknpm run deploy部署完成后 Wrangler 会输出 workers.dev 地址。首次新增或修改 Cron Trigger 最多可能需要约 15 分钟传播。
npx wrangler tail日志包含更新开始、基金总数、成功/失败数量、第三方耗时、KV 写入和旧缓存使用情况,不会记录刷新密钥、Cookie 或敏感请求头。
运行:
npx wrangler secret put REFRESH_TOKEN确认 wrangler.jsonc 中绑定名为 FUND_CACHE。无绑定时 Worker 仍能运行,但页面访问会直接查询 Provider,且无法缓存。
查看 npx wrangler tail。单只失败会显示 --,不会让整个接口失败。可将 USE_MOCK_DATA 改为 true 验证页面和部署。
普通访问会优先使用 300 秒内的 KV 快照。需要立即更新时使用带 Secret 的强制刷新接口。
Cron 只在北京时间周一至周五的交易时段请求 Provider,不处理法定节假日和调休。新增 Trigger 后也可能需要等待传播。
修改 wrangler.jsonc 后运行:
npm run types
npm run typecheck本项目按个人低频使用设计:静态资源优先由 Workers Static Assets 直接提供,API 才进入 Worker;新浪估值采用单次批量请求,不会为每只基金分别建立连接。持仓主题成功分析后 30 天内直接读 KV,不会随每分钟净值刷新重复分析。请关注 Cloudflare 当前免费额度、KV 写入额度和 Cron Trigger 数量。额度与规则可能调整,部署前以 Cloudflare 官方文档为准。