# tc.dxx **Repository Path**: eshax/tc.dxx ## Basic Information - **Project Name**: tc.dxx - **Description**: 题材看板 - 短线侠 - **Primary Language**: HTML - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-10 - **Last Updated**: 2026-10-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 短线侠 · 题材看板 参考[「选股通」题材看板](http://tc.xgt.eshax.top/)的页面布局与视觉风格,把数据源替换为 **短线侠**([duanxianxia.cn](https://duanxianxia.cn/))的涨停数据,做一版基于短线侠题材归属的题材看板。 > 选股通与短线侠对个股的题材归属口径不同,本项目的题材分类、题材名称完全采用**短线侠口径** > (即 `ztplate.json` 中的 `plate` 字段),页面呈现格式沿用选股通题材看板的网格卡片样式。 ## 快速开始 要求 Node.js >= 18(无任何第三方依赖)。 ```bash node server.js # 或 npm start ``` 浏览器打开 。端口可通过环境变量修改: ```bash PORT=8080 node server.js ``` ## 功能 - 按题材分组的涨停看板:题材卡片显示加粗的题材名,以及「封板 : 炸板」计数(如 `零售 4 : 1`) - 每行展示:连板数、股票代码、股票名称、涨跌幅(红涨绿跌) - 封板名称红色、炸板名称黄色,炸板在板数位标「炸」并排在该题材末尾 - 科创板(`30` / `68` 开头)与北证(`9` 开头)的个股用较明显的深灰底区分,名称颜色仍按涨停 / 炸板等状态显示 - 板数位显示「N天M板」的天数/板数(`N === M` 时只显示 `N`);一字板(全天封死未打开)行底色为更明显的红色、名称为亮白色 - 顶部工具栏:总股票数 / 题材数量 / 数据日期、自动更新开关、科创板开关、主板开关、关键词过滤、日期选择、上一日 / 下一日 - 板块开关:关闭时隐藏对应板块个股,卡片计数与顶部统计同步重算 - 主板(默认开启):`60` / `00` 开头 - 科创板(默认开启):`30` / `68` 开头 - 北证(默认开启):`9` 开头 - 空白网格不再补「无数据」占位卡片 - 每日数据自动落盘存档(`data/YYYY-MM-DD.json`),支持回看历史日期 - 近 30 天的历史日期会在浏览器 `localStorage` 缓存一份,第二次切换直接读本地;超过 30 天的日期仍每次从云端读取 ## 目录结构 ``` . ├── server.js # HTTP 服务:静态资源 + API,零依赖 ├── lib/ │ ├── duanxianxia.js # 短线侠数据源(ztplate / ztlive) │ ├── quote.js # 腾讯行情(补全当前价与涨跌幅) │ ├── board.js # 题材聚合,输出看板数据结构 │ └── store.js # 每日快照读写 ├── public/ # 前端页面 │ ├── index.html │ ├── style.css │ └── app.js └── data/ # 运行后生成的每日快照 ``` ## 数据来源 | 来源 | 接口 | 用途 | | --- | --- | --- | | 短线侠 | `https://duanxianxia.cn/vendor/stockdata/ztlive.json` | **当日涨停名单**,决定哪些股票进看板:名称、涨停原因、连板情况、涨停时间 | | 短线侠 | `https://duanxianxia.cn/vendor/stockdata/ztplate.json` | 股票 → 题材板块字典(`plate` / `concept`),**只用于查题材归属** | | 腾讯 | `https://qt.gtimg.cn/q=...` | 当前价、涨跌幅、换手率、涨停价(用于识别炸板) | ### 口径说明(重要) - `ztlive.json` 才是当日涨停名单(本次 83 只)。 - `ztplate.json` **不是**涨停名单,而是「股票 → 题材板块」的标签字典(本次 152 只), 其中约 45% 的股票当日并未涨停(实测抽样 40 只,涨停率 0%,涨跌幅区间 -5.6% ~ +7.29%)。 它对应短线侠页面上「板块」那一列(如 `零售+跨境电商`)。 若把 `ztplate.json` 当涨停名单来分组,会把大量非涨停股塞进题材卡片。 - 炸板判定:收盘价 < 当日涨停价即视为炸板(涨停价取自行情接口的第 47 号字段)。 短线侠接口只提供当日(最近一个交易日)快照,没有历史日期参数,因此历史数据由本项目抓取成功后 写入 `data/` 目录,供「上一日 / 下一日」浏览。 ## HTTP 接口 | 路径 | 说明 | | --- | --- | | `GET /api/board` | 当日看板数据(60 秒内存缓存,同时落盘快照) | | `GET /api/board?date=YYYY-MM-DD` | 指定日期的本地快照 | | `GET /api/board?refresh=1` | 强制刷新当日数据 | | `GET /api/dates` | 本地已存档的日期列表 | ## 样式主题 配色变量集中在 `public/style.css` 的 `:root` 中,可按需调整背景、涨跌色与强调色。 ## 部署 本项目**零第三方运行时依赖**(仅用 Node 内置模块)。有两种交付方式: - **源码部署**:把整个目录丢到服务器,`node server.js` 即可,无需 `npm install`。 - **单文件部署**:本地用 esbuild 打包成 **一个 `tc-dxx.js`**,拷到任意装了 Node >= 18 的机器上 `node tc-dxx.js` 即可,连 `public/` 目录都不需要带。 ### 环境变量 | 变量 | 默认值 | 说明 | | --- | --- | --- | | `PORT` | `3000` | 服务监听端口 | | `DXX_BASE` | `https://duanxianxia.cn/vendor/stockdata` | 短线侠数据源根地址,一般无需修改 | ### 打包成单文件(推荐交付方式) 只需在**本地(任意平台)**执行一次构建,产出 `dist/tc-dxx.mjs`: ```bash npm install # 安装 esbuild(仅开发依赖,运行时不需要) npm run build # 生成 dist/tc-dxx.mjs,前端资源已内联进文件 ``` `dist/tc-dxx.mjs` 是单文件,自带全部后端代码与 `public/` 前端资源。部署时: ```bash # 把 dist/tc-dxx.mjs 拷到服务器任意目录 node tc-dxx.mjs # 默认 3000 端口 PORT=8080 node tc-dxx.mjs # 自定义端口 ``` > 说明:单文件方案仍需目标机有 **Node.js >= 18**(但不需 `npm install`、不需源码目录)。 > 若要做到「连 Node 都不用装」的独立可执行文件,可用 [pkg](https://github.com/yao-pkg/pkg) 在**目标机所在操作系统**上构建 > (pkg 不支持跨平台编译,必须在要部署的 OS 上跑 `npm i -D pkg && npm run build:pkg`),本项目已预留 `pkg` 配置思路,按需启用即可。 ### 方式一:直接运行(内网 / 临时,源码方式) ```bash node server.js # 自定义端口 PORT=8080 node server.js ``` 浏览器访问 `http://<服务器IP>:3000`。 ### 方式二:后台守护(生产推荐) **使用 PM2**(需先 `npm i -g pm2`)。 #### 单文件方式(推荐,与「打包成单文件」配套) 先把 `dist/tc-dxx.mjs` 拷到服务器,再用 pm2 启动。端口通过 `PORT` 环境变量定义(默认 3000): ```bash # 默认端口 3000 pm2 start tc-dxx.mjs --name tc-dxx # 自定义端口(启动时用 PORT= 前缀传入) PORT=8080 pm2 start tc-dxx.mjs --name tc-dxx pm2 save # 保存进程列表(pm2 startup 可设开机自启) pm2 logs tc-dxx # 查看日志 ``` `PORT` 的定义规则(优先级从高到低): 1. **启动命令前的环境变量**:`PORT=8080 pm2 start tc-dxx.mjs` —— 仅本次进程生效。 2. **ecosystem 配置里的 `env.PORT`**:见下方配置文件方式,适合固定端口、统一管理。 3. **默认值**:代码里 `PORT` 未设置时回落到 `3000`。 如果希望端口配置写死在文件里、并带上自动重启等守护参数,用本项目根目录的 `ecosystem.config.cjs`(已配好 `script: dist/tc-dxx.mjs`、`cwd` 为项目根、`PORT=3000`、`autorestart`): ```bash pm2 start ecosystem.config.cjs # 启动(改端口改配置里的 env.PORT 即可) pm2 restart tc-dxx # 重新 npm run build 后热重启生效 ``` > 单文件方式只需目标机有 **Node ≥ 18**,无需 `npm install`;`data/` 快照目录会自动生成在 `cwd`(即 `ecosystem.config.cjs` 所在目录)。 #### 源码方式 若直接部署源码(整个目录),则将上面的 `tc-dxx.mjs` 换成 `server.js` 即可: ```bash pm2 start server.js --name tc-dxx PORT=8080 pm2 start server.js --name tc-dxx pm2 save pm2 logs tc-dxx ``` **使用 systemd**(新建 `/etc/systemd/system/tc-dxx.service`): ```ini [Unit] Description=短线侠题材看板 After=network.target [Service] WorkingDirectory=/opt/tc.dxx ExecStart=/usr/bin/node server.js Environment=PORT=3000 Restart=always User=www-data [Install] WantedBy=multi-user.target ``` ```bash sudo systemctl daemon-reload sudo systemctl enable --now tc-dxx ``` **最简(无工具)**: ```bash nohup node server.js > server.log 2>&1 & ``` ### 方式三:Docker 部署(可选) 项目零依赖,镜像基础用 `node:18-alpine` 即可,无需 `npm install`: ```dockerfile FROM node:18-alpine WORKDIR /app COPY package.json ./ COPY server.js lib public ./ RUN apk add --no-cache tzdata # 保证日志/快照用北京时间 EXPOSE 3000 CMD ["node", "server.js"] ``` 构建与运行: ```bash docker build -t tc-dxx . docker run -d --name tc-dxx -p 3000:3000 -v $(pwd)/data:/app/data tc-dxx ``` `-v` 挂载 `data/` 目录,保证历史快照容器重启后不丢失。 ### 反向代理(Nginx,可选) 如需用 80 / 443 域名访问,可在 Nginx 反代到本服务: ```nginx server { listen 80; server_name tc.example.com; location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } ``` ### 数据与更新说明 - 运行时会在 `data/` 目录生成每日快照 `data/YYYY-MM-DD.json`,用于历史回看;**部署时请保证该目录可写**(Docker 需挂载卷)。 - 数据来自短线侠的**当日涨停快照**,仅在 A 股交易时段(约 09:15–15:00)才有当日实时数据,收盘后返回的是最近一个交易日的数据。前端「自动更新」开关默认每 5 秒刷新一次。 - 服务启动时会先抓一次数据并落盘;之后 `/api/board` 有 60 秒内存缓存,命中缓存直接返回。 - 板块强度、情绪池、行情等接口偶发失败时,会沿用上一次的数据,避免题材强度或跌停数据在刷新时忽隐忽现。 - 自动刷新失败会立即重试(最多 3 次快速退避),前端同一时刻只允许一个网络请求,服务端也会合并并发刷新,避免请求风暴。 - 自动刷新最多等待 3 秒;超过后先返回上一次缓存,后台继续抓取并更新,避免上游接口卡住时页面长时间等待。 - API 响应启用 gzip 压缩(32KB 看板数据约压缩到 6KB);腾讯行情按单批请求,减少高延迟环境下的往返次数。 ## License [MIT](./LICENSE)