mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 07:16:51 +00:00
feat(export): add clickable sns count column in session list
This commit is contained in:
@@ -1559,6 +1559,38 @@
|
|||||||
color: var(--text-tertiary);
|
color: var(--text-tertiary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.row-sns-metric-btn {
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
min-height: 14px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.2;
|
||||||
|
color: var(--primary);
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--primary-hover);
|
||||||
|
text-decoration: underline;
|
||||||
|
text-underline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
outline: 2px solid color-mix(in srgb, var(--primary) 48%, transparent);
|
||||||
|
outline-offset: 2px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.loading {
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.row-message-stats {
|
.row-message-stats {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -2158,16 +2158,7 @@ function ExportPage() {
|
|||||||
setSessionSnsTimelineStatsLoading(false)
|
setSessionSnsTimelineStatsLoading(false)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const openSessionSnsTimeline = useCallback(() => {
|
const openSessionSnsTimelineByTarget = useCallback((target: SessionSnsTimelineTarget) => {
|
||||||
const normalizedSessionId = String(sessionDetail?.wxid || '').trim()
|
|
||||||
if (!isSingleContactSession(normalizedSessionId) || !sessionDetail) return
|
|
||||||
|
|
||||||
const target: SessionSnsTimelineTarget = {
|
|
||||||
username: normalizedSessionId,
|
|
||||||
displayName: sessionDetail.displayName || sessionDetail.remark || sessionDetail.nickName || normalizedSessionId,
|
|
||||||
avatarUrl: sessionDetail.avatarUrl
|
|
||||||
}
|
|
||||||
|
|
||||||
setSessionSnsTimelineTarget(target)
|
setSessionSnsTimelineTarget(target)
|
||||||
setSessionSnsTimelinePosts([])
|
setSessionSnsTimelinePosts([])
|
||||||
setSessionSnsTimelineHasMore(false)
|
setSessionSnsTimelineHasMore(false)
|
||||||
@@ -2175,7 +2166,7 @@ function ExportPage() {
|
|||||||
setSessionSnsTimelineLoading(false)
|
setSessionSnsTimelineLoading(false)
|
||||||
|
|
||||||
if (snsUserPostCountsStatus === 'ready') {
|
if (snsUserPostCountsStatus === 'ready') {
|
||||||
const count = Number(snsUserPostCounts[normalizedSessionId] || 0)
|
const count = Number(snsUserPostCounts[target.username] || 0)
|
||||||
setSessionSnsTimelineTotalPosts(Number.isFinite(count) ? Math.max(0, Math.floor(count)) : 0)
|
setSessionSnsTimelineTotalPosts(Number.isFinite(count) ? Math.max(0, Math.floor(count)) : 0)
|
||||||
setSessionSnsTimelineStatsLoading(false)
|
setSessionSnsTimelineStatsLoading(false)
|
||||||
} else {
|
} else {
|
||||||
@@ -2188,11 +2179,33 @@ function ExportPage() {
|
|||||||
}, [
|
}, [
|
||||||
loadSessionSnsTimelinePosts,
|
loadSessionSnsTimelinePosts,
|
||||||
loadSnsUserPostCounts,
|
loadSnsUserPostCounts,
|
||||||
sessionDetail,
|
|
||||||
snsUserPostCounts,
|
snsUserPostCounts,
|
||||||
snsUserPostCountsStatus
|
snsUserPostCountsStatus
|
||||||
])
|
])
|
||||||
|
|
||||||
|
const openSessionSnsTimeline = useCallback(() => {
|
||||||
|
const normalizedSessionId = String(sessionDetail?.wxid || '').trim()
|
||||||
|
if (!isSingleContactSession(normalizedSessionId) || !sessionDetail) return
|
||||||
|
|
||||||
|
const target: SessionSnsTimelineTarget = {
|
||||||
|
username: normalizedSessionId,
|
||||||
|
displayName: sessionDetail.displayName || sessionDetail.remark || sessionDetail.nickName || normalizedSessionId,
|
||||||
|
avatarUrl: sessionDetail.avatarUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
openSessionSnsTimelineByTarget(target)
|
||||||
|
}, [openSessionSnsTimelineByTarget, sessionDetail])
|
||||||
|
|
||||||
|
const openContactSnsTimeline = useCallback((contact: ContactInfo) => {
|
||||||
|
const normalizedSessionId = String(contact?.username || '').trim()
|
||||||
|
if (!isSingleContactSession(normalizedSessionId)) return
|
||||||
|
openSessionSnsTimelineByTarget({
|
||||||
|
username: normalizedSessionId,
|
||||||
|
displayName: contact.displayName || contact.remark || contact.nickname || normalizedSessionId,
|
||||||
|
avatarUrl: contact.avatarUrl
|
||||||
|
})
|
||||||
|
}, [openSessionSnsTimelineByTarget])
|
||||||
|
|
||||||
const loadMoreSessionSnsTimeline = useCallback(() => {
|
const loadMoreSessionSnsTimeline = useCallback(() => {
|
||||||
if (!sessionSnsTimelineTarget || sessionSnsTimelineLoading || sessionSnsTimelineLoadingMore || !sessionSnsTimelineHasMore) return
|
if (!sessionSnsTimelineTarget || sessionSnsTimelineLoading || sessionSnsTimelineLoadingMore || !sessionSnsTimelineHasMore) return
|
||||||
void loadSessionSnsTimelinePosts(sessionSnsTimelineTarget, { reset: false })
|
void loadSessionSnsTimelinePosts(sessionSnsTimelineTarget, { reset: false })
|
||||||
@@ -4058,6 +4071,9 @@ function ExportPage() {
|
|||||||
if (activeTab === 'former_friend') return '曾经的好友'
|
if (activeTab === 'former_friend') return '曾经的好友'
|
||||||
return '公众号'
|
return '公众号'
|
||||||
}, [activeTab])
|
}, [activeTab])
|
||||||
|
const shouldShowSnsColumn = useMemo(() => (
|
||||||
|
activeTab === 'private' || activeTab === 'former_friend'
|
||||||
|
), [activeTab])
|
||||||
|
|
||||||
const sessionRowByUsername = useMemo(() => {
|
const sessionRowByUsername = useMemo(() => {
|
||||||
const map = new Map<string, SessionRow>()
|
const map = new Map<string, SessionRow>()
|
||||||
@@ -5004,6 +5020,10 @@ function ExportPage() {
|
|||||||
const voiceMetric = metricToDisplay(mediaMetric?.voiceMessages)
|
const voiceMetric = metricToDisplay(mediaMetric?.voiceMessages)
|
||||||
const imageMetric = metricToDisplay(mediaMetric?.imageMessages)
|
const imageMetric = metricToDisplay(mediaMetric?.imageMessages)
|
||||||
const videoMetric = metricToDisplay(mediaMetric?.videoMessages)
|
const videoMetric = metricToDisplay(mediaMetric?.videoMessages)
|
||||||
|
const isSnsCountLoading = snsUserPostCountsStatus === 'loading' || snsUserPostCountsStatus === 'idle'
|
||||||
|
const snsRawCount = Number(snsUserPostCounts[contact.username] || 0)
|
||||||
|
const snsCount = Number.isFinite(snsRawCount) ? Math.max(0, Math.floor(snsRawCount)) : 0
|
||||||
|
const supportsSnsTimeline = isSingleContactSession(contact.username)
|
||||||
const openChatLabel = contact.type === 'friend'
|
const openChatLabel = contact.type === 'friend'
|
||||||
? '打开私聊'
|
? '打开私聊'
|
||||||
: contact.type === 'group'
|
: contact.type === 'group'
|
||||||
@@ -5086,6 +5106,24 @@ function ExportPage() {
|
|||||||
: videoMetric.text}
|
: videoMetric.text}
|
||||||
</strong>
|
</strong>
|
||||||
</div>
|
</div>
|
||||||
|
{shouldShowSnsColumn && (
|
||||||
|
<div className="row-media-metric">
|
||||||
|
{supportsSnsTimeline ? (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`row-sns-metric-btn ${isSnsCountLoading ? 'loading' : ''}`}
|
||||||
|
title={`查看 ${contact.displayName || contact.username} 的朋友圈`}
|
||||||
|
onClick={() => openContactSnsTimeline(contact)}
|
||||||
|
>
|
||||||
|
{isSnsCountLoading
|
||||||
|
? <Loader2 size={12} className="spin row-media-metric-icon" aria-label="朋友圈统计加载中" />
|
||||||
|
: `${snsCount.toLocaleString('zh-CN')} 条`}
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<strong className="row-media-metric-value">--</strong>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className="row-action-cell">
|
<div className="row-action-cell">
|
||||||
<div className="row-action-main">
|
<div className="row-action-main">
|
||||||
<button
|
<button
|
||||||
@@ -5121,6 +5159,7 @@ function ExportPage() {
|
|||||||
}, [
|
}, [
|
||||||
lastExportBySession,
|
lastExportBySession,
|
||||||
nowTick,
|
nowTick,
|
||||||
|
openContactSnsTimeline,
|
||||||
openSessionDetail,
|
openSessionDetail,
|
||||||
openSingleExport,
|
openSingleExport,
|
||||||
queuedSessionIds,
|
queuedSessionIds,
|
||||||
@@ -5131,6 +5170,9 @@ function ExportPage() {
|
|||||||
sessionMessageCounts,
|
sessionMessageCounts,
|
||||||
sessionRowByUsername,
|
sessionRowByUsername,
|
||||||
showSessionDetailPanel,
|
showSessionDetailPanel,
|
||||||
|
shouldShowSnsColumn,
|
||||||
|
snsUserPostCounts,
|
||||||
|
snsUserPostCountsStatus,
|
||||||
toggleSelectSession
|
toggleSelectSession
|
||||||
])
|
])
|
||||||
const handleContactsListWheelCapture = useCallback((event: WheelEvent<HTMLDivElement>) => {
|
const handleContactsListWheelCapture = useCallback((event: WheelEvent<HTMLDivElement>) => {
|
||||||
@@ -5395,6 +5437,9 @@ function ExportPage() {
|
|||||||
<span className="contacts-list-header-media">语音</span>
|
<span className="contacts-list-header-media">语音</span>
|
||||||
<span className="contacts-list-header-media">图片</span>
|
<span className="contacts-list-header-media">图片</span>
|
||||||
<span className="contacts-list-header-media">视频</span>
|
<span className="contacts-list-header-media">视频</span>
|
||||||
|
{shouldShowSnsColumn && (
|
||||||
|
<span className="contacts-list-header-media">朋友圈</span>
|
||||||
|
)}
|
||||||
<span className="contacts-list-header-actions">
|
<span className="contacts-list-header-actions">
|
||||||
{selectedCount > 0 && (
|
{selectedCount > 0 && (
|
||||||
<>
|
<>
|
||||||
|
|||||||
Reference in New Issue
Block a user