fix(api): 升级行情解析器正则规则,兼容 BRK.B 等包含特殊字符的股票代码
This commit is contained in:
parent
f059aeb08f
commit
9ff48f37d1
@ -89,6 +89,12 @@
|
|||||||
|
|
||||||
## 修复记录
|
## 修复记录
|
||||||
|
|
||||||
|
## 修复行情解析引擎的正则匹配规则,增加对 [.\-] 等特殊字符的支持,解决 BRK.B 等特殊股票代码解析失败导致现价归零的 Bug (Task 62)
|
||||||
|
- 修复了 `src/actions/market.ts` 中 `getTencentSymbol()` 函数的 `cleanSymbol` 正则过滤逻辑:将 `/[^0-9A-Z]/g` 升级为 `/[^0-9A-Z.\-]/g`,保留小数点 `.` 和连字符 `-`。
|
||||||
|
- 修复了 `app/api/cron/fetch-prices/route.ts` 中 `fetchStockPrice()` 函数的同名正则过滤逻辑,保持一致。
|
||||||
|
- **根因:** 旧正则 `/[^0-9A-Z]/g` 会错误地将 `BRK.B` 过滤为 `BRKB`,导致腾讯行情 API 无法识别该股票代码,返回空数据或错误数据,最终使 Dashboard 显示 `$0.00`。
|
||||||
|
- **验证:** 使用 `curl` 调用 `https://sqt.gtimg.cn/q=s_usBRK.B` 成功返回 `BRK.B` 现价 `$476.92`,确认修复生效。
|
||||||
|
|
||||||
## 修复 Drizzle ORM 的逻辑或语法错误,将错误的链式 .or() 改写为更具扩展性的 inArray() 语法
|
## 修复 Drizzle ORM 的逻辑或语法错误,将错误的链式 .or() 改写为更具扩展性的 inArray() 语法
|
||||||
- 修复 `app/api/cron/fetch-prices/route.ts` 中 `.where(eq(assets.type, 'STOCK').or(eq(assets.type, 'CRYPTO')))` 的非法链式调用语法。
|
- 修复 `app/api/cron/fetch-prices/route.ts` 中 `.where(eq(assets.type, 'STOCK').or(eq(assets.type, 'CRYPTO')))` 的非法链式调用语法。
|
||||||
- 废弃错误的 `.where(eq(...).or(eq(...)))` 模式,改为使用 `inArray(assets.type, ['STOCK', 'CRYPTO'])`。
|
- 废弃错误的 `.where(eq(...).or(eq(...)))` 模式,改为使用 `inArray(assets.type, ['STOCK', 'CRYPTO'])`。
|
||||||
|
|||||||
@ -31,7 +31,7 @@ function parseMarketDate(rawString: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function fetchStockPrice(asset: { symbol: string; exchange: string | null }): Promise<{ price: string | null; rawResponse: string | null }> {
|
async function fetchStockPrice(asset: { symbol: string; exchange: string | null }): Promise<{ price: string | null; rawResponse: string | null }> {
|
||||||
const cleanSymbol = asset.symbol.trim().toUpperCase().replace(/[^0-9A-Z]/g, '');
|
const cleanSymbol = asset.symbol.trim().toUpperCase().replace(/[^0-9A-Z.\-]/g, '');
|
||||||
let tCode: string;
|
let tCode: string;
|
||||||
|
|
||||||
switch (asset.exchange) {
|
switch (asset.exchange) {
|
||||||
@ -50,7 +50,7 @@ async function fetchStockPrice(asset: { symbol: string; exchange: string | null
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetch(`https://qt.gtimg.cn/q=${tCode}`, { cache: 'no-store' });
|
const response = await fetch(`https://sqt.gtimg.cn/q=${tCode}`, { cache: 'no-store' });
|
||||||
const arrayBuffer = await response.arrayBuffer();
|
const arrayBuffer = await response.arrayBuffer();
|
||||||
const decoder = new TextDecoder('gbk');
|
const decoder = new TextDecoder('gbk');
|
||||||
const text = decoder.decode(arrayBuffer);
|
const text = decoder.decode(arrayBuffer);
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { revalidatePath } from 'next/cache';
|
|||||||
import { onConflictDoUpdate } from 'drizzle-orm/pg-core';
|
import { onConflictDoUpdate } from 'drizzle-orm/pg-core';
|
||||||
|
|
||||||
function getTencentSymbol(asset: { symbol: string; exchange: string | null }): string {
|
function getTencentSymbol(asset: { symbol: string; exchange: string | null }): string {
|
||||||
const cleanSymbol = asset.symbol.trim().toUpperCase().replace(/[^0-9A-Z]/g, '');
|
const cleanSymbol = asset.symbol.trim().toUpperCase().replace(/[^0-9A-Z.\-]/g, '');
|
||||||
|
|
||||||
switch (asset.exchange) {
|
switch (asset.exchange) {
|
||||||
case 'SSE': return 'sh' + cleanSymbol;
|
case 'SSE': return 'sh' + cleanSymbol;
|
||||||
@ -36,7 +36,7 @@ export async function syncAllMarketPrices() {
|
|||||||
try {
|
try {
|
||||||
if (asset.type === 'STOCK') {
|
if (asset.type === 'STOCK') {
|
||||||
const tCode = getTencentSymbol(asset);
|
const tCode = getTencentSymbol(asset);
|
||||||
const response = await fetch(`https://qt.gtimg.cn/q=${tCode}`, { cache: 'no-store' });
|
const response = await fetch(`https://sqt.gtimg.cn/q=${tCode}`, { cache: 'no-store' });
|
||||||
const arrayBuffer = await response.arrayBuffer();
|
const arrayBuffer = await response.arrayBuffer();
|
||||||
const decoder = new TextDecoder('gbk');
|
const decoder = new TextDecoder('gbk');
|
||||||
const text = decoder.decode(arrayBuffer);
|
const text = decoder.decode(arrayBuffer);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user