()
| 612 | } |
| 613 | |
| 614 | async updateRelatedArticles() { |
| 615 | console.log('🔄 Updating article relations...'); |
| 616 | |
| 617 | // 获取所有文章的分析数据 |
| 618 | const articles = await new Promise((resolve, reject) => { |
| 619 | this.db.all(` |
| 620 | SELECT |
| 621 | i.number, |
| 622 | i.title, |
| 623 | a.css_properties, |
| 624 | a.techniques, |
| 625 | a.complexity_level |
| 626 | FROM issues i |
| 627 | JOIN article_analysis a ON i.number = a.issue_number |
| 628 | `, (err, rows) => { |
| 629 | if (err) reject(err); |
| 630 | else resolve(rows); |
| 631 | }); |
| 632 | }); |
| 633 | |
| 634 | // 计算文章间的相关性 |
| 635 | for (const article of articles) { |
| 636 | const related = articles |
| 637 | .filter(other => other.number !== article.number) |
| 638 | .map(other => { |
| 639 | const score = this.calculateRelationScore(article, other); |
| 640 | return { number: other.number, score }; |
| 641 | }) |
| 642 | .sort((a, b) => b.score - a.score) |
| 643 | .slice(0, 5) // 取前5个最相关的文章 |
| 644 | .map(r => r.number); |
| 645 | |
| 646 | // 更新相关文章 |
| 647 | await this.saveAnalysisToDatabase(article.number, { |
| 648 | ...article, |
| 649 | related_articles: JSON.stringify(related) |
| 650 | }); |
| 651 | } |
| 652 | } |
| 653 | |
| 654 | calculateRelationScore(article1, article2) { |
| 655 | let score = 0; |
nothing calls this directly
no test coverage detected