优化首页 Gitea Activity 展示
This commit is contained in:
parent
31796260cc
commit
d46f69c9a6
|
|
@ -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(/\/+$/, '');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue