mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-24 23:06:51 +00:00
@@ -16,6 +16,10 @@ export interface GroupMember {
|
||||
username: string
|
||||
displayName: string
|
||||
avatarUrl?: string
|
||||
nickname?: string
|
||||
alias?: string
|
||||
remark?: string
|
||||
groupNickname?: string
|
||||
}
|
||||
|
||||
export interface GroupMessageRank {
|
||||
@@ -211,14 +215,55 @@ class GroupAnalyticsService {
|
||||
}
|
||||
|
||||
const members = result.members as { username: string; avatarUrl?: string }[]
|
||||
const usernames = members.map((m) => m.username)
|
||||
const displayNames = await wcdbService.getDisplayNames(usernames)
|
||||
const usernames = members.map((m) => m.username).filter(Boolean)
|
||||
|
||||
const data: GroupMember[] = members.map((m) => ({
|
||||
username: m.username,
|
||||
displayName: displayNames.success && displayNames.map ? (displayNames.map[m.username] || m.username) : m.username,
|
||||
const [displayNames, groupNicknames] = await Promise.all([
|
||||
wcdbService.getDisplayNames(usernames),
|
||||
this.getGroupNicknamesForRoom(chatroomId)
|
||||
])
|
||||
|
||||
const contactMap = new Map<string, { remark?: string; nickName?: string; alias?: string }>()
|
||||
const concurrency = 6
|
||||
await this.parallelLimit(usernames, concurrency, async (username) => {
|
||||
const contactResult = await wcdbService.getContact(username)
|
||||
if (contactResult.success && contactResult.contact) {
|
||||
const contact = contactResult.contact as any
|
||||
contactMap.set(username, {
|
||||
remark: contact.remark || '',
|
||||
nickName: contact.nickName || contact.nick_name || '',
|
||||
alias: contact.alias || ''
|
||||
})
|
||||
} else {
|
||||
contactMap.set(username, { remark: '', nickName: '', alias: '' })
|
||||
}
|
||||
})
|
||||
|
||||
const myWxid = this.cleanAccountDirName(this.configService.get('myWxid') || '')
|
||||
const data: GroupMember[] = members.map((m) => {
|
||||
const wxid = m.username || ''
|
||||
const displayName = displayNames.success && displayNames.map ? (displayNames.map[wxid] || wxid) : wxid
|
||||
const contact = contactMap.get(wxid)
|
||||
const nickname = contact?.nickName || ''
|
||||
const remark = contact?.remark || ''
|
||||
const alias = contact?.alias || ''
|
||||
const rawGroupNickname = groupNicknames.get(wxid.toLowerCase()) || ''
|
||||
const normalizedWxid = this.cleanAccountDirName(wxid)
|
||||
const groupNickname = this.normalizeGroupNickname(
|
||||
rawGroupNickname,
|
||||
normalizedWxid === myWxid ? myWxid : wxid,
|
||||
''
|
||||
)
|
||||
|
||||
return {
|
||||
username: wxid,
|
||||
displayName,
|
||||
nickname,
|
||||
alias,
|
||||
remark,
|
||||
groupNickname,
|
||||
avatarUrl: m.avatarUrl
|
||||
}))
|
||||
}
|
||||
})
|
||||
|
||||
return { success: true, data }
|
||||
} catch (e) {
|
||||
|
||||
@@ -16,6 +16,10 @@ interface GroupMember {
|
||||
username: string
|
||||
displayName: string
|
||||
avatarUrl?: string
|
||||
nickname?: string
|
||||
alias?: string
|
||||
remark?: string
|
||||
groupNickname?: string
|
||||
}
|
||||
|
||||
interface GroupMessageRank {
|
||||
@@ -298,6 +302,10 @@ function GroupAnalyticsPage() {
|
||||
|
||||
const renderMemberModal = () => {
|
||||
if (!selectedMember) return null
|
||||
const nickname = (selectedMember.nickname || '').trim()
|
||||
const alias = (selectedMember.alias || '').trim()
|
||||
const remark = (selectedMember.remark || '').trim()
|
||||
const groupNickname = (selectedMember.groupNickname || '').trim()
|
||||
|
||||
return (
|
||||
<div className="member-modal-overlay" onClick={() => setSelectedMember(null)}>
|
||||
@@ -320,11 +328,40 @@ function GroupAnalyticsPage() {
|
||||
</div>
|
||||
<div className="detail-row">
|
||||
<span className="detail-label">昵称</span>
|
||||
<span className="detail-value">{selectedMember.displayName}</span>
|
||||
<button className="copy-btn" onClick={() => handleCopy(selectedMember.displayName, 'displayName')}>
|
||||
{copiedField === 'displayName' ? <Check size={14} /> : <Copy size={14} />}
|
||||
<span className="detail-value">{nickname || '未设置'}</span>
|
||||
{nickname && (
|
||||
<button className="copy-btn" onClick={() => handleCopy(nickname, 'nickname')}>
|
||||
{copiedField === 'nickname' ? <Check size={14} /> : <Copy size={14} />}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{alias && (
|
||||
<div className="detail-row">
|
||||
<span className="detail-label">微信号</span>
|
||||
<span className="detail-value">{alias}</span>
|
||||
<button className="copy-btn" onClick={() => handleCopy(alias, 'alias')}>
|
||||
{copiedField === 'alias' ? <Check size={14} /> : <Copy size={14} />}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{groupNickname && (
|
||||
<div className="detail-row">
|
||||
<span className="detail-label">群昵称</span>
|
||||
<span className="detail-value">{groupNickname}</span>
|
||||
<button className="copy-btn" onClick={() => handleCopy(groupNickname, 'groupNickname')}>
|
||||
{copiedField === 'groupNickname' ? <Check size={14} /> : <Copy size={14} />}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{remark && (
|
||||
<div className="detail-row">
|
||||
<span className="detail-label">备注</span>
|
||||
<span className="detail-value">{remark}</span>
|
||||
<button className="copy-btn" onClick={() => handleCopy(remark, 'remark')}>
|
||||
{copiedField === 'remark' ? <Check size={14} /> : <Copy size={14} />}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
4
src/types/electron.d.ts
vendored
4
src/types/electron.d.ts
vendored
@@ -219,6 +219,10 @@ export interface ElectronAPI {
|
||||
username: string
|
||||
displayName: string
|
||||
avatarUrl?: string
|
||||
nickname?: string
|
||||
alias?: string
|
||||
remark?: string
|
||||
groupNickname?: string
|
||||
}>
|
||||
error?: string
|
||||
}>
|
||||
|
||||
Reference in New Issue
Block a user