优化首页 Gitea Activity 展示

This commit is contained in:
SepComet 2026-05-07 09:09:29 +08:00
parent 31796260cc
commit d46f69c9a6
3 changed files with 100 additions and 13 deletions

View File

@ -269,7 +269,7 @@ function mapActivityFeed(
const repo = feed.repo?.full_name || fallback.fallbackRepo; const repo = feed.repo?.full_name || fallback.fallbackRepo;
const type = normalizeActivityType(feed.op_type); const type = normalizeActivityType(feed.op_type);
const message = const message =
clean(feed.content) || summarizeActivityMessage(feed.content) ||
clean(feed.comment?.body) || clean(feed.comment?.body) ||
clean(feed.issue?.title) || clean(feed.issue?.title) ||
clean(feed.pull_request?.title) || clean(feed.pull_request?.title) ||
@ -354,6 +354,28 @@ function clean(value?: string) {
return value?.replace(/\s+/g, ' ').trim() || ''; return value?.replace(/\s+/g, ' ').trim() || '';
} }
function summarizeActivityMessage(value?: string) {
const cleaned = clean(value);
if (!cleaned.startsWith('{')) {
return cleaned;
}
try {
const parsed = JSON.parse(cleaned) as {
HeadCommit?: {
Message?: string;
};
Commits?: Array<{
Message?: string;
}>;
};
return clean(parsed.HeadCommit?.Message) || clean(parsed.Commits?.[0]?.Message) || cleaned;
} catch {
return cleaned;
}
}
function trimTrailingSlash(value: string) { function trimTrailingSlash(value: string) {
return value.replace(/\/+$/, ''); return value.replace(/\/+$/, '');
} }

View File

@ -1,6 +1,7 @@
--- ---
import type { GiteaActivityData } from '../data/loaders'; import type { GiteaActivityData } from '../data/loaders';
import { site } from '../config'; import { site } from '../config';
import { formatDateTime } from '../utils/datetime';
import SyncMeta from './SyncMeta.astro'; import SyncMeta from './SyncMeta.astro';
interface Props { interface Props {
@ -26,14 +27,63 @@ const heatmap = Array.from({ length: heatmapSize }, (_, index) => {
); );
}); });
const recentActivities = activity.recent.slice(0, 3); function cleanText(value?: string) {
return value?.replace(/\s+/g, ' ').trim() || '';
}
function summarizeActivity(item: GiteaActivityData['recent'][number]) {
const fallbackMessage = cleanText(item.message) || 'Repository activity';
const fallbackTime = item.time;
if (!fallbackMessage.startsWith('{')) {
return {
...item,
message: fallbackMessage,
displayTime: formatDateTime(fallbackTime) || fallbackTime,
rawTime: fallbackTime,
};
}
try {
const parsed = JSON.parse(fallbackMessage) as {
HeadCommit?: {
Message?: string;
Timestamp?: string;
};
Commits?: Array<{
Message?: string;
Timestamp?: string;
}>;
};
const headCommit = parsed.HeadCommit ?? parsed.Commits?.[0];
const message = cleanText(headCommit?.Message) || fallbackMessage;
const rawTime = headCommit?.Timestamp || fallbackTime;
return {
...item,
message,
displayTime: formatDateTime(rawTime) || rawTime,
rawTime,
};
} catch {
return {
...item,
message: fallbackMessage,
displayTime: formatDateTime(fallbackTime) || fallbackTime,
rawTime: fallbackTime,
};
}
}
const recentActivities = activity.recent.slice(0, 3).map(summarizeActivity);
const isPlaceholder = activity.source === 'placeholder'; const isPlaceholder = activity.source === 'placeholder';
--- ---
<section class="panel activity-panel"> <section class="panel activity-panel">
<div class="section-heading" style="margin-bottom: 1rem;"> <div class="section-heading" style="margin-bottom: 1rem;">
<div> <div>
<span class="eyebrow">Gitea Activity</span> <span class="eyebrow activity-panel__eyebrow">Gitea Activity</span>
<h2>活跃度概览</h2> <h2>活跃度概览</h2>
<p> <p>
{isPlaceholder {isPlaceholder
@ -84,16 +134,16 @@ const isPlaceholder = activity.source === 'placeholder';
recentActivities.length > 0 ? ( recentActivities.length > 0 ? (
recentActivities.map((item) => ( recentActivities.map((item) => (
<article class="activity-item"> <article class="activity-item">
<strong class="mono">{item.repo}</strong> <p class="activity-item__repo mono">{item.repo}</p>
<p class="activity-copy">{item.message}</p> <p class="activity-copy">{item.message}</p>
<p class="activity-meta" style="margin-top: 0.55rem;"> <p class="activity-meta activity-item__meta">
<span>{item.time}</span> <time datetime={item.rawTime}>{item.displayTime}</time>
</p> </p>
</article> </article>
)) ))
) : ( ) : (
<article class="activity-item"> <article class="activity-item">
<strong class="mono">暂无同步活动</strong> <p class="activity-item__repo mono">暂无同步活动</p>
<p class="activity-copy">先运行一次 content:sync或等待后续接入真实 Gitea 数据源。</p> <p class="activity-copy">先运行一次 content:sync或等待后续接入真实 Gitea 数据源。</p>
</article> </article>
) )

View File

@ -495,17 +495,22 @@ main {
} }
.activity-panel .section-heading p, .activity-panel .section-heading p,
.activity-panel .section-heading .eyebrow,
.activity-panel .activity-copy, .activity-panel .activity-copy,
.activity-panel .activity-meta, .activity-panel .activity-meta,
.activity-panel .heatmap-legend { .activity-panel .heatmap-legend {
color: rgba(226, 232, 240, 0.86); color: rgba(226, 232, 240, 0.86);
} }
.activity-panel__eyebrow {
border: 1px solid rgba(147, 197, 253, 0.28);
background: rgba(37, 99, 235, 0.18);
color: #eff6ff;
}
.activity-grid { .activity-grid {
display: grid; display: grid;
grid-template-columns: 1.1fr 0.9fr; grid-template-columns: minmax(0, 1.3fr) minmax(18rem, 0.85fr);
gap: 1rem; gap: 1.25rem;
align-items: start; align-items: start;
} }
@ -545,19 +550,29 @@ main {
.activity-list { .activity-list {
display: grid; display: grid;
gap: 0.75rem; gap: 0.75rem;
min-width: 0;
} }
.activity-item { .activity-item {
min-width: 0;
padding: 0.95rem 1rem; padding: 0.95rem 1rem;
border: 1px solid rgba(148, 163, 184, 0.22); border: 1px solid rgba(148, 163, 184, 0.22);
border-radius: 1rem; border-radius: 1rem;
background: rgba(15, 23, 42, 0.32); background: rgba(15, 23, 42, 0.32);
} }
.activity-item strong { .activity-item__repo {
display: block; margin: 0 0 0.35rem;
margin-bottom: 0.25rem;
color: #fff; color: #fff;
font-size: 0.84rem;
}
.activity-panel .activity-copy {
overflow-wrap: anywhere;
}
.activity-item__meta {
margin-top: 0.55rem;
} }
.corner-gallery { .corner-gallery {