import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository, LessThan, MoreThanOrEqual } from 'typeorm'; import { BidItem } from '../entities/bid-item.entity'; @Injectable() export class BidsService { constructor( @InjectRepository(BidItem) private bidRepository: Repository, ) {} async findAll(query?: any) { const { page = 1, limit = 10, source, keyword } = query || {}; const qb = this.bidRepository.createQueryBuilder('bid'); if (source) { qb.andWhere('bid.source = :source', { source }); } if (keyword) { qb.andWhere('bid.title LIKE :keyword', { keyword: `%${keyword}%` }); } qb.orderBy('bid.publishDate', 'DESC') .skip((page - 1) * limit) .take(limit); const [items, total] = await qb.getManyAndCount(); return { items, total }; } getHighPriority() { return this.bidRepository.find({ where: { priority: LessThan(0) }, // This is just a placeholder logic, priority should be > 0 order: { priority: 'DESC', publishDate: 'DESC' }, take: 10, }); } // Update logic for priority async getHighPriorityCorrected() { return this.bidRepository.createQueryBuilder('bid') .where('bid.priority > 0') .orderBy('bid.priority', 'DESC') .addOrderBy('bid.publishDate', 'DESC') .limit(10) .getMany(); } async createOrUpdate(data: Partial) { // Use title or a hash of title to check for duplicates let item = await this.bidRepository.findOne({ where: { title: data.title } }); if (item) { Object.assign(item, data); return this.bidRepository.save(item); } return this.bidRepository.save(data); } async cleanOldData() { const thirtyDaysAgo = new Date(); thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30); return this.bidRepository.delete({ createdAt: LessThan(thirtyDaysAgo), }); } async getSources() { const result = await this.bidRepository .createQueryBuilder('bid') .select('DISTINCT bid.source') .where('bid.source IS NOT NULL') .orderBy('bid.source', 'ASC') .getRawMany(); return result.map((item: any) => item.source); } async getRecentBids() { const thirtyDaysAgo = new Date(); thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30); thirtyDaysAgo.setHours(0, 0, 0, 0); return this.bidRepository .createQueryBuilder('bid') .where('bid.publishDate >= :thirtyDaysAgo', { thirtyDaysAgo }) .orderBy('bid.publishDate', 'DESC') .getMany(); } async getBidsByDateRange(startDate?: string, endDate?: string, keywords?: string[]) { const qb = this.bidRepository.createQueryBuilder('bid'); if (startDate) { const start = new Date(startDate); start.setHours(0, 0, 0, 0); qb.andWhere('bid.publishDate >= :startDate', { startDate: start }); } if (endDate) { const end = new Date(endDate); end.setHours(23, 59, 59, 999); qb.andWhere('bid.publishDate <= :endDate', { endDate: end }); } if (keywords && keywords.length > 0) { const keywordConditions = keywords.map((keyword, index) => { return `bid.title LIKE :keyword${index}`; }).join(' OR '); qb.andWhere(`(${keywordConditions})`, keywords.reduce((params, keyword, index) => { params[`keyword${index}`] = `%${keyword}%`; return params; }, {})); } return qb.orderBy('bid.publishDate', 'DESC').getMany(); } async getCrawlInfoAddStats() { const { InjectRepository } = require('@nestjs/typeorm'); const { Repository } = require('typeorm'); const { CrawlInfoAdd } = require('../../crawler/entities/crawl-info-add.entity'); // 获取每个来源的最新一次爬虫记录 const query = ` SELECT source, count, latestPublishDate, error, createdAt as latestUpdate FROM crawl_info_add WHERE id IN ( SELECT MAX(id) FROM crawl_info_add GROUP BY source ) ORDER BY source ASC `; const results = await this.bidRepository.query(query); return results.map((item: any) => ({ source: item.source, count: item.count, latestUpdate: item.latestUpdate, latestPublishDate: item.latestPublishDate, error: item.error, })); } }