feat(sns): show per-contact post counts in filter panel

This commit is contained in:
tisonhuang
2026-03-02 13:43:21 +08:00
parent bc739dc4a0
commit 204baa52ab
7 changed files with 86 additions and 15 deletions

View File

@@ -7,6 +7,7 @@ interface Contact {
username: string
displayName: string
avatarUrl?: string
postCount?: number
}
interface SnsFilterPanelProps {
@@ -150,7 +151,10 @@ export const SnsFilterPanel: React.FC<SnsFilterPanelProps> = ({
onClick={() => toggleUserSelection(contact.username)}
>
<Avatar src={contact.avatarUrl} name={contact.displayName} size={36} shape="rounded" />
<span className="contact-name">{contact.displayName}</span>
<div className="contact-meta">
<span className="contact-name">{contact.displayName}</span>
<span className="contact-post-count">{Math.max(0, Number(contact.postCount || 0))} </span>
</div>
</div>
))}
{filteredContacts.length === 0 && (

View File

@@ -1055,9 +1055,16 @@
margin-bottom: 0;
/* Remove margin to merge */
.contact-name {
color: var(--primary);
font-weight: 600;
.contact-meta {
.contact-name {
color: var(--primary);
font-weight: 600;
}
.contact-post-count {
color: var(--primary);
opacity: 0.9;
}
}
/* If the NEXT item is also selected */
@@ -1080,13 +1087,26 @@
/* Compensate for missing border */
}
.contact-name {
.contact-meta {
flex: 1;
font-size: 14px;
color: var(--text-secondary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
display: flex;
flex-direction: column;
gap: 2px;
.contact-name {
font-size: 14px;
color: var(--text-secondary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.contact-post-count {
font-size: 12px;
color: var(--text-tertiary);
line-height: 1.2;
}
}
}
}

View File

@@ -11,6 +11,7 @@ interface Contact {
displayName: string
avatarUrl?: string
type?: 'friend' | 'former_friend' | 'sns_only'
postCount: number
}
interface SnsOverviewStats {
@@ -251,11 +252,16 @@ export default function SnsPage() {
const loadContacts = useCallback(async () => {
setContactsLoading(true)
try {
// 并行获取联系人列表朋友圈发布者列表
const [contactsResult, snsResult] = await Promise.all([
// 并行获取联系人列表朋友圈发布者列表和每个发布者的动态条数
const [contactsResult, snsResult, snsCountsResult] = await Promise.all([
window.electronAPI.chat.getContacts(),
window.electronAPI.sns.getSnsUsernames()
window.electronAPI.sns.getSnsUsernames(),
window.electronAPI.sns.getUserPostCounts()
])
const snsPostCountMap = new Map<string, number>(
Object.entries(snsCountsResult.success ? (snsCountsResult.data || {}) : {})
.map(([username, count]) => [username, Math.max(0, Number(count || 0))])
)
// 以联系人为基础,按 username 去重
const contactMap = new Map<string, Contact>()
@@ -268,7 +274,8 @@ export default function SnsPage() {
username: c.username,
displayName: c.displayName,
avatarUrl: c.avatarUrl,
type: c.type === 'former_friend' ? 'former_friend' : 'friend'
type: c.type === 'former_friend' ? 'former_friend' : 'friend',
postCount: snsPostCountMap.get(c.username) || 0
})
}
}
@@ -278,7 +285,7 @@ export default function SnsPage() {
if (snsResult.success && snsResult.usernames) {
for (const u of snsResult.usernames) {
if (!contactMap.has(u)) {
contactMap.set(u, { username: u, displayName: u, type: 'sns_only' })
contactMap.set(u, { username: u, displayName: u, type: 'sns_only', postCount: snsPostCountMap.get(u) || 0 })
}
}
}

View File

@@ -591,6 +591,7 @@ export interface ElectronAPI {
onExportProgress: (callback: (payload: { current: number; total: number; status: string }) => void) => () => void
selectExportDir: () => Promise<{ canceled: boolean; filePath?: string }>
getSnsUsernames: () => Promise<{ success: boolean; usernames?: string[]; error?: string }>
getUserPostCounts: () => Promise<{ success: boolean; data?: Record<string, number>; error?: string }>
getExportStatsFast: () => Promise<{ success: boolean; data?: { totalPosts: number; totalFriends: number }; error?: string }>
getExportStats: () => Promise<{ success: boolean; data?: { totalPosts: number; totalFriends: number }; error?: string }>
installBlockDeleteTrigger: () => Promise<{ success: boolean; alreadyInstalled?: boolean; error?: string }>