diff --git a/src/crawler/services/cdt_target.ts b/src/crawler/services/cdt_target.ts index ea5372b..88960f3 100644 --- a/src/crawler/services/cdt_target.ts +++ b/src/crawler/services/cdt_target.ts @@ -337,7 +337,7 @@ export const CdtCrawler = { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`Failed to crawl ${this.name}: ${errorMessage}`); - return allResults; + throw error; } finally { await page.close(); } diff --git a/src/crawler/services/ceic_target.ts b/src/crawler/services/ceic_target.ts index 1dc822e..b31bfd6 100644 --- a/src/crawler/services/ceic_target.ts +++ b/src/crawler/services/ceic_target.ts @@ -242,7 +242,7 @@ export const CeicCrawler = { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`Crawl failed: ${errorMessage}`); - return allResults; + throw error; } finally { if (page) await page.close(); } diff --git a/src/crawler/services/cgnpc_target.ts b/src/crawler/services/cgnpc_target.ts index 4557f51..b3b7e86 100644 --- a/src/crawler/services/cgnpc_target.ts +++ b/src/crawler/services/cgnpc_target.ts @@ -229,7 +229,7 @@ export const CgnpcCrawler = { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`Failed to crawl ${this.name}: ${errorMessage}`); - return allResults; + throw error; } finally { await page.close(); } diff --git a/src/crawler/services/chdtp_target.ts b/src/crawler/services/chdtp_target.ts index f920f03..598b41a 100644 --- a/src/crawler/services/chdtp_target.ts +++ b/src/crawler/services/chdtp_target.ts @@ -159,7 +159,7 @@ export const ChdtpCrawler = { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`Failed to crawl ${this.name}: ${errorMessage}`); - return allResults; // Return what we have so far + throw error; } finally { await page.close(); } diff --git a/src/crawler/services/chng_target.ts b/src/crawler/services/chng_target.ts index 3ee5db1..0c6cc8b 100644 --- a/src/crawler/services/chng_target.ts +++ b/src/crawler/services/chng_target.ts @@ -366,7 +366,7 @@ export const ChngCrawler = { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`Crawl failed: ${errorMessage}`); - return allResults; + throw error; } finally { if (page) await page.close(); } diff --git a/src/crawler/services/cnncecp_target.ts b/src/crawler/services/cnncecp_target.ts index e59b760..3b2cc82 100644 --- a/src/crawler/services/cnncecp_target.ts +++ b/src/crawler/services/cnncecp_target.ts @@ -228,7 +228,7 @@ export const CnncecpCrawler = { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`Failed to crawl ${this.name}: ${errorMessage}`); - return allResults; + throw error; } finally { await page.close(); } diff --git a/src/crawler/services/cnooc_target.ts b/src/crawler/services/cnooc_target.ts index 7aa742d..f55c8ba 100644 --- a/src/crawler/services/cnooc_target.ts +++ b/src/crawler/services/cnooc_target.ts @@ -229,7 +229,7 @@ export const CnoocCrawler = { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`Failed to crawl ${this.name}: ${errorMessage}`); - return allResults; + throw error; } finally { await page.close(); } diff --git a/src/crawler/services/eps_target.ts b/src/crawler/services/eps_target.ts index 970ae90..d1fd88b 100644 --- a/src/crawler/services/eps_target.ts +++ b/src/crawler/services/eps_target.ts @@ -229,7 +229,7 @@ export const EpsCrawler = { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`Failed to crawl ${this.name}: ${errorMessage}`); - return allResults; + throw error; } finally { await page.close(); } diff --git a/src/crawler/services/espic_target.ts b/src/crawler/services/espic_target.ts index 07068c2..8a7cd5b 100644 --- a/src/crawler/services/espic_target.ts +++ b/src/crawler/services/espic_target.ts @@ -269,7 +269,7 @@ export const EspicCrawler = { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`Failed to crawl ${this.name}: ${errorMessage}`); - return allResults; + throw error; } finally { await page.close(); } diff --git a/src/crawler/services/powerbeijing_target.ts b/src/crawler/services/powerbeijing_target.ts index 8702f9a..eb65ea0 100644 --- a/src/crawler/services/powerbeijing_target.ts +++ b/src/crawler/services/powerbeijing_target.ts @@ -229,7 +229,7 @@ export const PowerbeijingCrawler = { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`Failed to crawl ${this.name}: ${errorMessage}`); - return allResults; + throw error; } finally { await page.close(); } diff --git a/src/crawler/services/sdicc_target.ts b/src/crawler/services/sdicc_target.ts index 8a7c464..7eb0ae2 100644 --- a/src/crawler/services/sdicc_target.ts +++ b/src/crawler/services/sdicc_target.ts @@ -239,7 +239,7 @@ export const SdiccCrawler = { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`Failed to crawl ${this.name}: ${errorMessage}`); - return allResults; + throw error; } finally { await page.close(); } diff --git a/src/crawler/services/szecp_target.ts b/src/crawler/services/szecp_target.ts index 2fe9c59..dc241e4 100644 --- a/src/crawler/services/szecp_target.ts +++ b/src/crawler/services/szecp_target.ts @@ -248,7 +248,7 @@ export const SzecpCrawler = { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`Crawl failed: ${errorMessage}`); - return allResults; + throw error; } finally { if (page) await page.close(); } diff --git a/uni-app-version/src/utils/api.ts b/uni-app-version/src/utils/api.ts new file mode 100644 index 0000000..5e723b4 --- /dev/null +++ b/uni-app-version/src/utils/api.ts @@ -0,0 +1,105 @@ +/** + * API 请求封装 + */ + +// 从环境变量读取 API 基础地址 +const BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3000' + +interface RequestOptions { + url: string + method?: 'GET' | 'POST' | 'PUT' | 'DELETE' + data?: any + header?: Record +} + +/** + * 统一请求方法 + */ +function request(options: RequestOptions): Promise { + return new Promise((resolve, reject) => { + uni.request({ + url: BASE_URL + options.url, + method: options.method || 'GET', + data: options.data || {}, + header: { + 'Content-Type': 'application/json', + ...options.header + }, + success: (res) => { + if (res.statusCode >= 200 && res.statusCode < 300) { + resolve(res.data as T) + } else { + reject(new Error(`请求失败: ${res.statusCode} ${(res.data as any)?.message || ''}`)) + } + }, + fail: (err) => { + console.error('请求错误:', err) + reject(new Error(`网络请求失败: ${err.errMsg || '未知错误'}`)) + } + }) + }) +} + +// 数据类型定义 +export interface BidItem { + id: string + title: string + url: string + publishDate: string + source: string + pin: boolean + createdAt: string + updatedAt: string +} + +export interface AiRecommendation { + id: string + title: string + confidence: number + createdAt: string +} + +export interface CrawlInfoStat { + source: string + count: number + latestUpdate: string + latestPublishDate: string + error: string +} + +/** + * 获取置顶投标项目 + */ +export function getPinnedBids(): Promise { + return request({ + url: '/api/bids/pinned', + method: 'GET' + }) +} + +/** + * 获取 AI 推荐 + */ +export function getAiRecommendations(): Promise { + return request({ + url: '/api/ai/latest-recommendations', + method: 'GET' + }) +} + +/** + * 获取爬虫统计信息 + */ +export function getCrawlInfoStats(): Promise { + return request({ + url: '/api/bids/crawl-info-stats', + method: 'GET' + }) +} + +export default { + request, + getPinnedBids, + getAiRecommendations, + getCrawlInfoStats +}