96 lines
2.9 KiB
TypeScript
Executable File
96 lines
2.9 KiB
TypeScript
Executable File
import type { Article } from '@fenghuo/common';
|
|
|
|
|
|
/**
|
|
* 格式化数字显示
|
|
*/
|
|
export function formatNumber(num: number): string {
|
|
if (num >= 10000) {
|
|
return (num / 10000).toFixed(1) + 'w';
|
|
}
|
|
if (num >= 1000) {
|
|
return (num / 1000).toFixed(1) + 'k';
|
|
}
|
|
return num.toString();
|
|
}
|
|
|
|
/**
|
|
* 筛选文章
|
|
*/
|
|
export function filterArticles(
|
|
articles: Article[],
|
|
searchTerm: string,
|
|
statusFilter: string,
|
|
categoryFilter: string,
|
|
): Article[] {
|
|
return articles.filter((article) => {
|
|
const matchesSearch =
|
|
article.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
|
article.excerpt?.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
|
(article.terms ?? []).some((term) => term.name.toLowerCase().includes(searchTerm.toLowerCase()));
|
|
|
|
const matchesStatus = statusFilter === 'all' || article.status === statusFilter;
|
|
|
|
const matchesCategory =
|
|
categoryFilter === 'all' || (article.terms ?? []).some((term) => term.name === categoryFilter);
|
|
|
|
return matchesSearch && matchesStatus && matchesCategory;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 排序文章
|
|
*/
|
|
export function sortArticles(articles: Article[], sortBy: string): Article[] {
|
|
return [...articles].sort((a, b) => {
|
|
switch (sortBy) {
|
|
case 'created-desc':
|
|
return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
|
|
case 'created-asc':
|
|
return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
|
|
case 'published-desc':
|
|
if (!a.publishedAt) return 1;
|
|
if (!b.publishedAt) return -1;
|
|
return new Date(b.publishedAt).getTime() - new Date(a.publishedAt).getTime();
|
|
case 'published-asc':
|
|
if (!a.publishedAt) return 1;
|
|
if (!b.publishedAt) return -1;
|
|
return new Date(a.publishedAt).getTime() - new Date(b.publishedAt).getTime();
|
|
case 'title-asc':
|
|
return a.title.localeCompare(b.title);
|
|
case 'title-desc':
|
|
return b.title.localeCompare(a.title);
|
|
case 'views-desc':
|
|
return b.viewCount - a.viewCount;
|
|
case 'views-asc':
|
|
return a.viewCount - b.viewCount;
|
|
default:
|
|
return 0;
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 获取唯一分类列表
|
|
*/
|
|
export function getUniqueCategories(articles: Article[]): string[] {
|
|
const all: string[] = [];
|
|
articles.forEach((a) => {
|
|
if (a.terms) all.push(...a.terms.map((t) => t.name));
|
|
});
|
|
return Array.from(new Set(all));
|
|
}
|
|
|
|
/**
|
|
* 分页处理
|
|
*/
|
|
export function paginateArray<T>(array: T[], page: number, pageSize: number): T[] {
|
|
return array.slice((page - 1) * pageSize, page * pageSize);
|
|
}
|
|
|
|
/**
|
|
* 计算总页数
|
|
*/
|
|
export function calculateTotalPages(totalItems: number, pageSize: number): number {
|
|
return Math.ceil(totalItems / pageSize);
|
|
}
|