mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-24 23:06:51 +00:00
修复群昵称读取错误的问题
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -57,3 +57,4 @@ Thumbs.db
|
|||||||
|
|
||||||
wcdb/
|
wcdb/
|
||||||
*info
|
*info
|
||||||
|
*.md
|
||||||
|
|||||||
@@ -67,6 +67,38 @@ class AnalyticsService {
|
|||||||
return new Set(this.getExcludedUsernamesList())
|
return new Set(this.getExcludedUsernamesList())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private escapeSqlValue(value: string): string {
|
||||||
|
return value.replace(/'/g, "''")
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getAliasMap(usernames: string[]): Promise<Record<string, string>> {
|
||||||
|
const map: Record<string, string> = {}
|
||||||
|
if (usernames.length === 0) return map
|
||||||
|
|
||||||
|
const chunkSize = 200
|
||||||
|
for (let i = 0; i < usernames.length; i += chunkSize) {
|
||||||
|
const chunk = usernames.slice(i, i + chunkSize)
|
||||||
|
const inList = chunk.map((u) => `'${this.escapeSqlValue(u)}'`).join(',')
|
||||||
|
if (!inList) continue
|
||||||
|
const sql = `
|
||||||
|
SELECT username, alias
|
||||||
|
FROM contact
|
||||||
|
WHERE username IN (${inList})
|
||||||
|
`
|
||||||
|
const result = await wcdbService.execQuery('contact', null, sql)
|
||||||
|
if (!result.success || !result.rows) continue
|
||||||
|
for (const row of result.rows as Record<string, any>[]) {
|
||||||
|
const username = row.username || ''
|
||||||
|
const alias = row.alias || ''
|
||||||
|
if (username && alias) {
|
||||||
|
map[username] = alias
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return map
|
||||||
|
}
|
||||||
|
|
||||||
private cleanAccountDirName(name: string): string {
|
private cleanAccountDirName(name: string): string {
|
||||||
const trimmed = name.trim()
|
const trimmed = name.trim()
|
||||||
if (!trimmed) return trimmed
|
if (!trimmed) return trimmed
|
||||||
@@ -419,7 +451,7 @@ class AnalyticsService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getExcludeCandidates(): Promise<{ success: boolean; data?: Array<{ username: string; displayName: string; avatarUrl?: string }>; error?: string }> {
|
async getExcludeCandidates(): Promise<{ success: boolean; data?: Array<{ username: string; displayName: string; avatarUrl?: string; wechatId?: string }>; error?: string }> {
|
||||||
try {
|
try {
|
||||||
const conn = await this.ensureConnected()
|
const conn = await this.ensureConnected()
|
||||||
if (!conn.success || !conn.cleanedWxid) return { success: false, error: conn.error }
|
if (!conn.success || !conn.cleanedWxid) return { success: false, error: conn.error }
|
||||||
@@ -435,9 +467,10 @@ class AnalyticsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const usernameList = Array.from(usernames)
|
const usernameList = Array.from(usernames)
|
||||||
const [displayNames, avatarUrls] = await Promise.all([
|
const [displayNames, avatarUrls, aliasMap] = await Promise.all([
|
||||||
wcdbService.getDisplayNames(usernameList),
|
wcdbService.getDisplayNames(usernameList),
|
||||||
wcdbService.getAvatarUrls(usernameList)
|
wcdbService.getAvatarUrls(usernameList),
|
||||||
|
this.getAliasMap(usernameList)
|
||||||
])
|
])
|
||||||
|
|
||||||
const entries = usernameList.map((username) => {
|
const entries = usernameList.map((username) => {
|
||||||
@@ -447,7 +480,9 @@ class AnalyticsService {
|
|||||||
const avatarUrl = avatarUrls.success && avatarUrls.map
|
const avatarUrl = avatarUrls.success && avatarUrls.map
|
||||||
? avatarUrls.map[username]
|
? avatarUrls.map[username]
|
||||||
: undefined
|
: undefined
|
||||||
return { username, displayName, avatarUrl }
|
const alias = aliasMap[username]
|
||||||
|
const wechatId = alias || (!username.startsWith('wxid_') ? username : '')
|
||||||
|
return { username, displayName, avatarUrl, wechatId }
|
||||||
})
|
})
|
||||||
|
|
||||||
return { success: true, data: entries }
|
return { success: true, data: entries }
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ class ExportService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 清理昵称:去除前后空白和特殊字符
|
// 清理昵称:去除前后空白和特殊字符
|
||||||
nickname = nickname.trim().replace(/[\x00-\x1F\x7F]/g, '')
|
nickname = this.normalizeGroupNickname(nickname)
|
||||||
|
|
||||||
// 只保存有效的群昵称(长度 > 0 且 < 50)
|
// 只保存有效的群昵称(长度 > 0 且 < 50)
|
||||||
if (nickname && nickname.length > 0 && nickname.length < 50) {
|
if (nickname && nickname.length > 0 && nickname.length < 50) {
|
||||||
@@ -432,6 +432,15 @@ class ExportService {
|
|||||||
return /^[0-9a-fA-F]+$/.test(s)
|
return /^[0-9a-fA-F]+$/.test(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private normalizeGroupNickname(value: string): string {
|
||||||
|
const trimmed = (value || '').trim()
|
||||||
|
if (!trimmed) return ''
|
||||||
|
const cleaned = trimmed.replace(/[\x00-\x1F\x7F]/g, '')
|
||||||
|
if (!cleaned) return ''
|
||||||
|
if (/^[,"'“”‘’,、]+$/.test(cleaned)) return ''
|
||||||
|
return cleaned
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据用户偏好获取显示名称
|
* 根据用户偏好获取显示名称
|
||||||
*/
|
*/
|
||||||
@@ -2034,7 +2043,7 @@ class ExportService {
|
|||||||
? contact.contact.nickName
|
? contact.contact.nickName
|
||||||
: (senderInfo.displayName || senderWxid)
|
: (senderInfo.displayName || senderWxid)
|
||||||
const senderRemark = contact.success && contact.contact?.remark ? contact.contact.remark : ''
|
const senderRemark = contact.success && contact.contact?.remark ? contact.contact.remark : ''
|
||||||
const senderGroupNickname = groupNicknamesMap.get(senderWxid?.toLowerCase() || '') || ''
|
const senderGroupNickname = this.normalizeGroupNickname(groupNicknamesMap.get(senderWxid?.toLowerCase() || '') || '')
|
||||||
|
|
||||||
// 使用用户偏好的显示名称
|
// 使用用户偏好的显示名称
|
||||||
const senderDisplayName = this.getPreferredDisplayName(
|
const senderDisplayName = this.getPreferredDisplayName(
|
||||||
@@ -2080,7 +2089,7 @@ class ExportService {
|
|||||||
? sessionContact.contact.remark
|
? sessionContact.contact.remark
|
||||||
: ''
|
: ''
|
||||||
const sessionGroupNickname = isGroup
|
const sessionGroupNickname = isGroup
|
||||||
? (groupNicknamesMap.get(sessionId.toLowerCase()) || '')
|
? this.normalizeGroupNickname(groupNicknamesMap.get(sessionId.toLowerCase()) || '')
|
||||||
: ''
|
: ''
|
||||||
|
|
||||||
// 使用用户偏好的显示名称
|
// 使用用户偏好的显示名称
|
||||||
@@ -2447,7 +2456,7 @@ class ExportService {
|
|||||||
|
|
||||||
// 获取群昵称 (仅群聊且完整列模式)
|
// 获取群昵称 (仅群聊且完整列模式)
|
||||||
if (isGroup && !useCompactColumns && senderWxid) {
|
if (isGroup && !useCompactColumns && senderWxid) {
|
||||||
senderGroupNickname = groupNicknamesMap.get(senderWxid.toLowerCase()) || ''
|
senderGroupNickname = this.normalizeGroupNickname(groupNicknamesMap.get(senderWxid.toLowerCase()) || '')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "weflow",
|
"name": "weflow",
|
||||||
"version": "1.4.4",
|
"version": "1.5.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "weflow",
|
"name": "weflow",
|
||||||
"version": "1.4.4",
|
"version": "1.5.0",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"better-sqlite3": "^12.5.0",
|
"better-sqlite3": "^12.5.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "weflow",
|
"name": "weflow",
|
||||||
"version": "1.4.4",
|
"version": "1.5.0",
|
||||||
"description": "WeFlow",
|
"description": "WeFlow",
|
||||||
"main": "dist-electron/main.js",
|
"main": "dist-electron/main.js",
|
||||||
"author": "cc",
|
"author": "cc",
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ interface ExcludeCandidate {
|
|||||||
username: string
|
username: string
|
||||||
displayName: string
|
displayName: string
|
||||||
avatarUrl?: string
|
avatarUrl?: string
|
||||||
|
wechatId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const normalizeUsername = (value: string) => value.trim().toLowerCase()
|
const normalizeUsername = (value: string) => value.trim().toLowerCase()
|
||||||
@@ -167,7 +168,8 @@ function AnalyticsPage() {
|
|||||||
.filter((candidate) => {
|
.filter((candidate) => {
|
||||||
const query = excludeQuery.trim().toLowerCase()
|
const query = excludeQuery.trim().toLowerCase()
|
||||||
if (!query) return true
|
if (!query) return true
|
||||||
const haystack = `${candidate.displayName} ${candidate.username}`.toLowerCase()
|
const wechatId = candidate.wechatId || ''
|
||||||
|
const haystack = `${candidate.displayName} ${candidate.username} ${wechatId}`.toLowerCase()
|
||||||
return haystack.includes(query)
|
return haystack.includes(query)
|
||||||
})
|
})
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
@@ -464,6 +466,7 @@ function AnalyticsPage() {
|
|||||||
<div className="exclude-list">
|
<div className="exclude-list">
|
||||||
{visibleExcludeCandidates.map((candidate) => {
|
{visibleExcludeCandidates.map((candidate) => {
|
||||||
const isChecked = draftExcluded.has(normalizeUsername(candidate.username))
|
const isChecked = draftExcluded.has(normalizeUsername(candidate.username))
|
||||||
|
const wechatId = candidate.wechatId?.trim() || candidate.username
|
||||||
return (
|
return (
|
||||||
<label key={candidate.username} className={`exclude-item ${isChecked ? 'active' : ''}`}>
|
<label key={candidate.username} className={`exclude-item ${isChecked ? 'active' : ''}`}>
|
||||||
<input
|
<input
|
||||||
@@ -476,7 +479,7 @@ function AnalyticsPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="exclude-info">
|
<div className="exclude-info">
|
||||||
<span className="exclude-name">{candidate.displayName}</span>
|
<span className="exclude-name">{candidate.displayName}</span>
|
||||||
<span className="exclude-username">{candidate.username}</span>
|
<span className="exclude-username">{wechatId}</span>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
)
|
)
|
||||||
|
|||||||
1
src/types/electron.d.ts
vendored
1
src/types/electron.d.ts
vendored
@@ -191,6 +191,7 @@ export interface ElectronAPI {
|
|||||||
username: string
|
username: string
|
||||||
displayName: string
|
displayName: string
|
||||||
avatarUrl?: string
|
avatarUrl?: string
|
||||||
|
wechatId?: string
|
||||||
}>
|
}>
|
||||||
error?: string
|
error?: string
|
||||||
}>
|
}>
|
||||||
|
|||||||
Reference in New Issue
Block a user