# 行业分类 **Repository Path**: tumanba_1/industry-classification ## Basic Information - **Project Name**: 行业分类 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-01 - **Last Updated**: 2026-09-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 申万行业分类展示系统 基于申万行业分类数据(JSON)的本地可视化页面,支持三级分级展示、搜索、排序,以及通过萝卜投研(datayes)接口同步各行业的股票列表。 支持两种运行形态:**浏览器访问**(开发/日常使用)与 **Electron 桌面端**(打包分发)。 ## 目录结构 ``` stock_luobo/ ├── web/ 前端静态资源(server.py 的 STATIC_ROOT) │ ├── index.html 页面主体(树形展示、搜索、排序、弹窗、同步逻辑) │ ├── data.js 行业分类数据(挂载在 window.INDUSTRY_DATA) │ └── 申万行业分类萝卜.json 原始数据文件(源数据,页面不直接引用) │ ├── backend/ Python 后端 │ ├── server.py 本地服务器:静态文件 + 萝卜投研 API 代理 + 登录 Cookie 管理 │ └── login_helper.py Playwright 静默扫码登录脚本(由 server.py 按需启动) │ ├── electron/ Electron 主进程 │ └── main.js 托管 server 子进程 + 创建应用窗口 │ ├── data/ 运行时数据(DATA_ROOT,开发态;已 gitignore) │ ├── captured_cookies.json 捕获的登录 Cookie(自动生成,勿提交) │ └── .server_port server 启动后写入的实际端口 │ ├── package.json NPM 配置(scripts / electron-builder 打包配置) ├── .gitignore └── README.md ``` ### 路径约定(三个根目录) server.py 内部将路径分为三类,开发态与打包态自动切换: | 常量 | 内容 | 开发态 | 打包态 | |------|------|--------|--------| | `STATIC_ROOT` | 只读前端资源 | `web/` | `resources/`(exe 同级) | | `DATA_ROOT` | 可写运行时数据 | `data/` | Electron `userData` | | `BACKEND_ROOT` | Python 脚本 | `backend/` | 无(打包态不可用) | 打包态可通过 `--data-dir ` 参数或 `STOCKLUOBO_DATA_DIR` 环境变量覆盖数据目录。 ## 环境要求 - Python 3.x(无需第三方依赖;如需扫码登录另装 `playwright`) - Node.js 18+ 与 npm(仅 Electron 桌面端开发/打包需要) - 现代浏览器(Chrome / Edge 等) ## 启动方式 ### 方式一:浏览器访问(推荐日常使用) ```bash # 直接运行(等价于 python backend/server.py) npm run serve ``` 启动后访问: 指定端口 / 数据目录: ```bash python backend/server.py --port 8000 --data-dir ./data ``` > 注意:必须通过 `server.py` 访问,直接双击 `index.html` 打开时,树形展示可用,但股票数据同步功能会因跨域限制失效。 ### 方式二:Electron 桌面端(开发态) ```bash npm install # 首次需安装依赖 npm start # Electron 启动:spawn server 子进程 → 打开应用窗口 ``` 开发态下 Electron 会自动调用 `python backend/server.py --port 0 --data-dir ./data`,无需手动启动 server。 ### 方式三:打包为 Windows 桌面应用 ```bash npm run dist # = PyInstaller 编译 server.exe + electron-builder 打包 ``` 产物位于 `release/`: | 产物 | 说明 | |------|------| | `StockLuobo 1.0.0.exe` | 便携版,双击直接运行,无需安装 | | `StockLuobo Setup 1.0.0.exe` | NSIS 安装包,可选安装目录、创建桌面快捷方式 | | `win-unpacked/` | 解压目录版,直接运行其中的 `StockLuobo.exe` | > 打包版限制:无 Python/Playwright 运行时,「一键扫码登录」自动降级为引导手动粘贴 Cookie;浏览器访问方式无此限制。 ## NPM Scripts 一览 | 命令 | 作用 | |------|------| | `npm run serve` | 启动本地服务器(浏览器访问模式) | | `npm start` | Electron 开发态启动 | | `npm run build:server` | 仅用 PyInstaller 编译 `backend/server.py` → `dist/server.exe` | | `npm run dist` | 完整打包:编译 server.exe → electron-builder 产出安装包/便携版 | ## 功能说明 ### 基础展示 - 三级行业树形展示(L1 / L2 / L3,颜色区分) - 点击行展开/收起子级;工具栏支持「全部展开 / 全部收起」 - 头部统计:一级、二级、三级行业总数 - 每个一级行业显示:二级数量、三级分类总数徽章 ### 数据来源与加载顺序 1. 优先读取 localStorage 缓存(`sw_industry_structure`) 2. 无缓存时 fallback 到静态 `data.js` 3. 已登录状态下后台调用 `/api/industry-structure` 拉取最新分类,成功后覆盖缓存并重新渲染 ### 搜索与排序 - 统一搜索框:同时匹配行业(名称/ID/代码)与已同步股票(代码/名称,模糊匹配),命中行业自动展开层级并高亮;提示命中数量,回车打开第一个含匹配股票的行业列表,列表内匹配行高亮并滚动定位 - 行内排序:点击「二级 N」「三级 N」「股票 N」徽章即按对应数量对所有层级排序,点击三次为一个循环——降序 ▼ → 升序 ▲ → 取消排序(恢复默认顺序,未同步的排在最后) - 股票徽章旁的「列表」按钮:查看该行业股票列表弹窗 ### 股票数据同步 1. 点击「**一键扫码登录**」→ 项目页通过 `/api/run-login` 启动独立 Chromium 浏览器(弹出窗口) 2. Playwright 自动走完:访问 robo.datayes.com → 点登录按钮 → 登录弹窗默认就是微信扫码视图(二维码已渲染) 3. **你在弹出的浏览器窗口里用微信扫码确认**(3 分钟超时)→ Playwright 自动捕获所有 Set-Cookie(含 cloud-sso-token 等登录态),持久化到 `data/captured_cookies.json`,浏览器自动关闭 4. 项目页 Cookie 轮询检测到新登录态 → **自动填充保存**,同时自动拉取最新行业分类数据,直接点行业行「同步」即可查股票列表 > 也可选「微信快捷登录(项目页内完成)」——iframe 打开萝卜投研登录页,用弹窗内的密码/短信登录。微信扫码路径通过 Playwright 真实浏览器闭环(之前纯 HTTP 代理无法运行 cloud-portal 的换码 JS)。 ### 注销登录 / 更换账号 - 点击「注销登录」并确认:server.py 会先带当前 Cookie 调官方 `usermaster/logout.json` 使会话失效,然后清空 Cookie 罐与 `data/captured_cookies.json`,同时清除项目页保存的 Cookie 及本地缓存的行业分类数据 - 注销后重新点「微信快捷登录」→ 登录窗口内重新登录即可切换到新的微信账号 - 说明:扫码成功一次后,Cookie 有效期内打开代理页面均为自动登录(会话复用),无需重复扫码;登录检测仅在点击登录按钮后的 10 分钟武装窗口内生效,平时浏览不会误触发 > 手动方式仍可用:在 robo.datayes.com 登录后,F12 → 网络 → 任意 gw.datayes.com 请求 → 复制请求头 Cookie 粘贴保存。 ### 股票列表查看 - 点击「列表」按钮弹出列表弹窗 - 表格列动态生成,常见字段自动映射中文表头(代码、名称、最新价、涨跌幅、市值等) - 点击表头排序:数字列按数值排序,文本列按拼音排序;再次点击切换升/降序 ### 同步变更通知 - 每次同步后对比上次数据,Toast 提示新增(📈)/ 减少(📉)/ 首次同步(✨),可展开查看具体股票列表 - 行业树上的趋势徽章:`股票 540 ▲3 ▼2` - 同步历史保存在 localStorage `sw_stock_history`(每行业最近 30 条) ## 数据存储 | 数据 | 存储位置 | Key / 文件 | |------|----------|-----------| | 登录 Cookie | 浏览器 localStorage | `datayes_cookie` | | 登录 Cookie(服务端) | `data/captured_cookies.json` | — | | 股票列表缓存 | 浏览器 localStorage | `sw_stock_cache` | | 行业分类缓存 | 浏览器 localStorage | `sw_industry_structure` | | 同步历史 | 浏览器 localStorage | `sw_stock_history` | 清除浏览器站点数据后,需要重新配置 Cookie 并重新同步。 ## API 说明 ### 本地代理接口(server.py 提供) | 接口 | 说明 | |------|------| | `GET /api/industry/quotes?industryId={id}` | 行业股票列表(自动携带登录 Cookie) | | `GET /api/industry-structure` | 行业分类树(实时从上游拉取) | | `GET /api/captured-cookie` | 查询已捕获的 Cookie 与鉴权状态 | | `POST /api/seed-cookie` | 页面用 localStorage 旧 Cookie 预热服务端 | | `POST /api/logout` | 注销登录 | | `POST /api/run-login` | 启动 Playwright 辅助登录(弹出浏览器扫码) | | `POST /api/login-arm` / `POST /api/login-disarm` | 登录流程武装标记 | ### 上游接口 ``` GET https://gw.datayes.com/rrp_adventure/web/industry/ticker/quotes ?pageSize=1000&industryId={行业ID}&pageNow=1&sortField=&sortOrder= GET https://gw.datayes.com/rrp_adventure/industry/structure ``` ## 常见问题 **同步提示「接口需要登录」?** Cookie 未设置或已过期,按上述步骤重新获取并保存。 **为什么必须用 server.py?** 浏览器 CORS 策略禁止本地页面直接请求 datayes 接口;且登录 Cookie 为 HttpOnly,前端 JS 无法读取。`server.py` 在服务端转发请求并携带 Cookie,解决以上两个问题。请勿使用公共 CORS 代理,会导致登录 Cookie 泄露给第三方。 **Electron 打包版点「一键扫码登录」没反应?** 打包版内无 Python/Playwright 运行时,点击后会自动展开「手动 Cookie」面板,按提示粘贴 Cookie 即可。需要完整扫码登录功能请用浏览器访问模式(`npm run serve`)。 **端口被占用?** `server.py` 支持 `--port 0`(系统自动分配空闲端口);Electron 模式默认即用动态端口,通过 `data/.server_port` 文件回传实际端口。