diff --git a/Memory.md b/Memory.md index a3e4a04..1a7a205 100644 --- a/Memory.md +++ b/Memory.md @@ -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() 语法 - 修复 `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'])`。 diff --git a/app/api/cron/fetch-prices/route.ts b/app/api/cron/fetch-prices/route.ts index 09d1c15..a0d2b64 100644 --- a/app/api/cron/fetch-prices/route.ts +++ b/app/api/cron/fetch-prices/route.ts @@ -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 }> { - 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; switch (asset.exchange) { @@ -50,7 +50,7 @@ async function fetchStockPrice(asset: { symbol: string; exchange: string | null 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 decoder = new TextDecoder('gbk'); const text = decoder.decode(arrayBuffer); diff --git a/src/actions/market.ts b/src/actions/market.ts index d2729c9..65d8a1a 100644 --- a/src/actions/market.ts +++ b/src/actions/market.ts @@ -8,7 +8,7 @@ import { revalidatePath } from 'next/cache'; import { onConflictDoUpdate } from 'drizzle-orm/pg-core'; 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) { case 'SSE': return 'sh' + cleanSymbol; @@ -36,7 +36,7 @@ export async function syncAllMarketPrices() { try { if (asset.type === 'STOCK') { 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 decoder = new TextDecoder('gbk'); const text = decoder.decode(arrayBuffer);