From bd9f070195e3c2606e92fe4a931066571eba5b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B3=E6=B8=85=E7=88=BD?= Date: Mon, 12 May 2025 11:58:13 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E7=A7=81=E5=9F=9F=E6=93=8D=E7=9B=98?= =?UTF-8?q?=E6=89=8B=20-=20=E8=B4=A6=E5=8F=B7=E8=AF=A6=E6=83=85/=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=E6=A6=82=E8=A7=88=20=E5=AF=B9=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cunkebao/api/wechat-accounts.ts | 224 +++--------- Cunkebao/app/wechat-accounts/[id]/page.tsx | 342 +++++++++++------- Server/application/cunkebao/config/route.php | 2 +- ...GetWechatOnDeviceSummarizeV1Controller.php | 6 +- 4 files changed, 261 insertions(+), 313 deletions(-) diff --git a/Cunkebao/api/wechat-accounts.ts b/Cunkebao/api/wechat-accounts.ts index 0f761498..df4a654e 100644 --- a/Cunkebao/api/wechat-accounts.ts +++ b/Cunkebao/api/wechat-accounts.ts @@ -2,9 +2,40 @@ import { api } from "@/lib/api"; import { ServerWechatAccountsResponse, QueryWechatAccountParams, - WechatAccountDetailResponse } from "@/types/wechat-account"; +// 添加接口返回数据类型定义 +interface WechatAccountSummary { + accountAge: string; + activityLevel: { + allTimes: number; + dayTimes: number; + }; + accountWeight: { + scope: number; + ageWeight: number; + activityWeigth: number; + restrictWeight: number; + realNameWeight: number; + }; + statistics: { + todayAdded: number; + addLimit: number; + }; + restrictions: { + id: number; + level: string; + reason: string; + date: string; + }[]; +} + +interface WechatAccountSummaryResponse { + code: number; + msg: string; + data: WechatAccountSummary; +} + /** * 获取微信账号列表 * @param params 查询参数 @@ -24,15 +55,6 @@ export const fetchWechatAccountList = async (params: QueryWechatAccountParams = return api.get(`/v1/device/wechats?${queryParams.toString()}`); }; -/** - * 获取微信账号详情 - * @param id 微信账号ID - * @returns 微信账号详情响应 - */ -export const fetchWechatAccountDetail = async (id: string | number): Promise => { - return api.get(`/v1/device/wechats/${id}`); -}; - /** * 刷新微信账号状态 * @returns 刷新结果 @@ -115,173 +137,35 @@ export const transformWechatAccount = (serverAccount: any): import("@/types/wech }; }; -/** - * 将服务端的微信账号详情转换为前端详情页面所需的格式 - * @param detailResponse 服务端微信账号详情响应 - * @returns 前端页面所需的微信账号详情格式 - */ -export const transformWechatAccountDetail = (detailResponse: WechatAccountDetailResponse): any => { - if (!detailResponse || !detailResponse.data) { - return null; - } - - const { basicInfo, statistics, accountInfo, restrictions, friends } = detailResponse.data; - - // 设备信息处理 - 改进处理方式 - let deviceId = ''; - let deviceName = ''; - - if (basicInfo.deviceInfo) { - // 尝试解析设备信息字符串 - const deviceInfoParts = basicInfo.deviceInfo.split(' '); - if (deviceInfoParts.length > 0) { - // 提取数字部分作为设备ID,确保是整数 - const possibleId = deviceInfoParts[0].trim(); - // 验证是否为数字 - deviceId = /^\d+$/.test(possibleId) ? possibleId : ''; - - // 提取设备名称 - if (deviceInfoParts.length > 1) { - deviceName = deviceInfoParts[1].replace(/[()]/g, '').trim(); - } - } - } - - // 如果从deviceInfo无法获取有效的设备ID,直接使用微信账号ID作为备选 - if (!deviceId && basicInfo.id) { - deviceId = basicInfo.id.toString(); - } - - // 如果没有设备名称,使用备用名称 - if (!deviceName) { - deviceName = '未命名设备'; - } - - // 账号年龄计算 - let accountAgeYears = 0; - let accountAgeMonths = 0; - - if (accountInfo.createTime) { - const createDate = new Date(accountInfo.createTime); - const currentDate = new Date(); - const diffInMonths = (currentDate.getFullYear() - createDate.getFullYear()) * 12 + - (currentDate.getMonth() - createDate.getMonth()); - - accountAgeYears = Math.floor(diffInMonths / 12); - accountAgeMonths = diffInMonths % 12; - } - - // 转换限制记录 - const restrictionRecords = restrictions?.map((restriction, index) => ({ - id: `${index}`, - date: restriction.startTime, - reason: restriction.reason, - recoveryTime: restriction.endTime, - type: mapRestrictionType(restriction.type) - })) || []; - - // 转换好友数据 - const transformedFriends = friends?.map(friend => ({ - id: friend.id.toString(), - avatar: friend.avatar || `/placeholder.svg?height=40&width=40&text=${friend.nickname?.[0] || ''}`, - nickname: friend.nickname, - wechatId: friend.wechatId, - remark: '', // 服务端未提供 - addTime: friend.createTime, - lastInteraction: '', // 服务端未提供 - tags: [], // 服务端未提供 - region: friend.region || '', - source: '', // 服务端未提供 - notes: '', // 服务端未提供 - })) || []; - - // 创建每周统计数据(模拟数据,服务端未提供) - const weeklyStats = Array.from({ length: 7 }, (_, i) => ({ - date: `Day ${i + 1}`, - friends: Math.floor(Math.random() * 50) + 50, - messages: Math.floor(Math.random() * 100) + 100, - })); - - return { - id: basicInfo.id.toString(), - avatar: basicInfo.avatar || '', - nickname: basicInfo.nickname || '', - wechatId: basicInfo.wechatId || '', - deviceId, - deviceName, - friendCount: statistics.totalFriend || 0, - todayAdded: 0, // 服务端未提供,默认为0 - status: basicInfo.status === '在线' ? 'normal' : 'abnormal', - lastActive: accountInfo.lastUpdateTime || new Date().toLocaleString(), - messageCount: statistics.thirtyDayMsgCount || 0, - activeRate: 0, // 服务端未提供,默认为0 - accountAge: { - years: accountAgeYears, - months: accountAgeMonths, - }, - totalChats: statistics.sevenDayMsgCount + statistics.yesterdayMsgCount || 0, - chatFrequency: Math.floor((statistics.sevenDayMsgCount || 0) / 7), // 每日平均聊天次数 - restrictionRecords, - isVerified: true, // 服务端未提供,默认为true - firstMomentDate: accountInfo.createTime || '', - accountWeight: accountInfo.weight || 50, - weightFactors: { - restrictionFactor: restrictionRecords.length > 0 ? 0.8 : 1.0, - verificationFactor: 1.0, - ageFactor: Math.min(1.0, accountAgeYears * 0.1 + 0.5), - activityFactor: statistics.totalFriend > 0 ? 0.9 : 0.7, - }, - weeklyStats, - friends: transformedFriends, - }; -}; - -/** - * 将服务端的限制类型映射为前端类型 - * @param type 服务端限制类型 - * @returns 前端限制类型 - */ -const mapRestrictionType = (type: string): "friend_limit" | "marketing" | "spam" | "other" => { - const typeMap: Record = { - 'friend': 'friend_limit', - 'marketing': 'marketing', - 'spam': 'spam' - }; - - return typeMap[type] || 'other'; -}; - /** * 获取微信好友列表 * @param wechatId 微信账号ID * @param page 页码 - * @param limit 每页数量 - * @param keyword 搜索关键词 + * @param pageSize 每页数量 + * @param searchQuery 搜索关键词 * @returns 好友列表数据 */ -export const fetchWechatFriends = async ( - wechatId: string | number, - page: number = 1, - limit: number = 20, - keyword: string = "" -): Promise<{ code: number; msg: string; data: any }> => { +export const fetchWechatFriends = async (wechatId: string, page: number = 1, pageSize: number = 20, searchQuery: string = '') => { try { - const params = new URLSearchParams({ - wechatId: String(wechatId), - page: String(page), - limit: String(limit) - }); - - if (keyword) { - params.append('keyword', keyword); - } - - const url = `/v1/device/wechats/friends?${params.toString()}`; - const response = await api.get<{ code: number; msg: string; data: any }>(url); - - return response; + const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/v1/device/wechats/${wechatId}/friends?page=${page}&pageSize=${pageSize}&search=${searchQuery}`); + const data = await response.json(); + return data; } catch (error) { - console.error('获取微信好友列表失败:', error); + console.error("获取好友列表失败:", error); throw error; } -} \ No newline at end of file +}; + +/** + * 获取微信账号概览信息 + * @param id 微信账号ID + * @returns 微信账号概览信息 + */ +export const fetchWechatAccountSummary = async (id: string): Promise => { + try { + return api.get(`/v1/device/wechats/${id}/summary`); + } catch (error) { + console.error("获取账号概览失败:", error); + throw error; + } +}; \ No newline at end of file diff --git a/Cunkebao/app/wechat-accounts/[id]/page.tsx b/Cunkebao/app/wechat-accounts/[id]/page.tsx index 708d6ce0..9d594436 100644 --- a/Cunkebao/app/wechat-accounts/[id]/page.tsx +++ b/Cunkebao/app/wechat-accounts/[id]/page.tsx @@ -44,7 +44,7 @@ import { PaginationPrevious, } from "@/components/ui/pagination" import { toast } from "@/components/ui/use-toast" -import { fetchWechatAccountDetail, transformWechatAccountDetail, fetchWechatFriends } from "@/api/wechat-accounts" +import { fetchWechatFriends, fetchWechatAccountSummary } from "@/api/wechat-accounts" interface RestrictionRecord { id: string @@ -87,13 +87,12 @@ interface WechatAccountDetail { lastActive: string messageCount: number activeRate: number - // 新增和修改的字段 accountAge: { years: number months: number } totalChats: number - chatFrequency: number // 每日平均聊天次数 + chatFrequency: number restrictionRecords: RestrictionRecord[] isVerified: boolean firstMomentDate: string @@ -112,9 +111,35 @@ interface WechatAccountDetail { friends: WechatFriend[] } +interface WechatAccountSummary { + accountAge: string; + activityLevel: { + allTimes: number; + dayTimes: number; + }; + accountWeight: { + scope: number; + ageWeight: number; + activityWeigth: number; + restrictWeight: number; + realNameWeight: number; + }; + statistics: { + todayAdded: number; + addLimit: number; + }; + restrictions: { + id: number; + level: string; + reason: string; + date: string; + }[]; +} + export default function WechatAccountDetailPage({ params }: { params: { id: string } }) { const router = useRouter() const [account, setAccount] = useState(null) + const [accountSummary, setAccountSummary] = useState(null) const [showRestrictions, setShowRestrictions] = useState(false) const [showTransferConfirm, setShowTransferConfirm] = useState(false) const [showFriendDetail, setShowFriendDetail] = useState(false) @@ -151,9 +176,28 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri try { const decodedData = JSON.parse(decodeURIComponent(dataParam)); setInitialData(decodedData); + // 使用初始数据设置account + const mockData = generateMockAccountData(); + if (decodedData) { + mockData.avatar = decodedData.avatar; + mockData.nickname = decodedData.nickname; + mockData.status = decodedData.status; + mockData.wechatId = decodedData.wechatId; + mockData.deviceName = decodedData.deviceName; + } + setAccount(mockData); + setFriendsTotal(mockData.friendCount); + setIsLoading(false); } catch (error) { console.error('解析初始数据失败:', error); + setIsLoading(false); } + } else { + // 如果没有初始数据,使用模拟数据 + const mockData = generateMockAccountData(); + setAccount(mockData); + setFriendsTotal(mockData.friendCount); + setIsLoading(false); } }, []); @@ -422,79 +466,73 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri }; }, [friendsLoadingRef.current, friendsObserver.current]); - useEffect(() => { - // 模拟API调用获取账号详情 - const fetchAccount = async () => { - try { - setIsLoading(true) - - // 调用API获取微信账号详情 - const response = await fetchWechatAccountDetail(params.id) - - if (response && response.code === 200) { - // 转换数据格式 - const transformedAccount = transformWechatAccountDetail(response) - // 使用初始数据覆盖API返回的部分字段 - if (initialData) { - transformedAccount.avatar = initialData.avatar; - transformedAccount.nickname = initialData.nickname; - transformedAccount.status = initialData.status; - transformedAccount.wechatId = initialData.wechatId; - transformedAccount.deviceName = initialData.deviceName; - } - setAccount(transformedAccount) - - // 如果有好友总数,更新friendsTotal状态 - if (transformedAccount && transformedAccount.friendCount > 0) { - setFriendsTotal(transformedAccount.friendCount); - } - } else { - toast({ - title: "获取微信账号详情失败", - description: response?.msg || "请稍后再试", - variant: "destructive" - }) - // 获取失败时使用模拟数据 - const mockData = generateMockAccountData(); - // 使用初始数据覆盖模拟数据的部分字段 - if (initialData) { - mockData.avatar = initialData.avatar; - mockData.nickname = initialData.nickname; - mockData.status = initialData.status; - mockData.wechatId = initialData.wechatId; - mockData.deviceName = initialData.deviceName; - } - setAccount(mockData); - // 更新好友总数 - setFriendsTotal(mockData.friendCount); - } - } catch (error) { - console.error("获取微信账号详情失败:", error) - toast({ - title: "获取微信账号详情失败", - description: "请检查网络连接或稍后再试", - variant: "destructive" - }) - // 请求出错时使用模拟数据 - const mockData = generateMockAccountData(); - // 使用初始数据覆盖模拟数据的部分字段 - if (initialData) { - mockData.avatar = initialData.avatar; - mockData.nickname = initialData.nickname; - mockData.status = initialData.status; - mockData.wechatId = initialData.wechatId; - mockData.deviceName = initialData.deviceName; - } - setAccount(mockData); - // 更新好友总数 - setFriendsTotal(mockData.friendCount); - } finally { - setIsLoading(false) - } + // 计算账号年龄 + const calculateAccountAge = (registerTime: string) => { + const register = new Date(registerTime); + const now = new Date(); + const years = now.getFullYear() - register.getFullYear(); + const months = now.getMonth() - register.getMonth(); + + if (months < 0) { + return { + years: years - 1, + months: months + 12 + }; } + + return { + years, + months + }; + }; - fetchAccount() - }, [params.id, initialData]) + // 获取账号概览数据 + const fetchSummaryData = useCallback(async () => { + try { + setIsLoading(true); + const response = await fetchWechatAccountSummary(params.id); + if (response.code === 200) { + setAccountSummary(response.data); + } else { + toast({ + title: "获取账号概览失败", + description: response.msg || "请稍后再试", + variant: "destructive" + }); + } + } catch (error) { + console.error("获取账号概览失败:", error); + toast({ + title: "获取账号概览失败", + description: "请检查网络连接或稍后再试", + variant: "destructive" + }); + } finally { + setIsLoading(false); + } + }, [params.id]); + + // 在页面加载和切换到概览标签时获取数据 + useEffect(() => { + if (activeTab === "overview") { + fetchSummaryData(); + } + }, [activeTab, fetchSummaryData]); + + // 在初始加载时获取数据 + useEffect(() => { + if (activeTab === "overview") { + fetchSummaryData(); + } + }, [fetchSummaryData, activeTab]); + + // 处理标签切换 + const handleTabChange = (value: string) => { + setActiveTab(value); + if (value === "overview") { + fetchSummaryData(); + } + }; if (!account) { return
加载中...
@@ -618,7 +656,7 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri - + 账号概览 @@ -634,8 +672,16 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri 账号年龄 -
{formatAccountAge(account.accountAge)}
-
注册时间:{account.firstMomentDate}
+ {accountSummary && ( + <> +
+ {formatAccountAge(calculateAccountAge(accountSummary.accountAge))} +
+
+ 注册时间:{new Date(accountSummary.accountAge).toLocaleDateString()} +
+ + )} @@ -643,8 +689,12 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri 活跃程度 -
{account.chatFrequency}次/天
-
总聊天数:{account.totalChats.toLocaleString()}
+ {accountSummary && ( + <> +
{accountSummary.activityLevel.dayTimes}次/天
+
总聊天数:{accountSummary.activityLevel.allTimes.toLocaleString()}
+ + )}
@@ -655,34 +705,40 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri 账号权重评估 -
- {account.accountWeight} - -
- -

{getWeightDescription(account.accountWeight)}

-
-
- 账号年龄 - - {(account.weightFactors.ageFactor * 100).toFixed(0)}% -
-
- 活跃度 - - {(account.weightFactors.activityFactor * 100).toFixed(0)}% -
-
- 限制影响 - - {(account.weightFactors.restrictionFactor * 100).toFixed(0)}% -
-
- 实名认证 - - {(account.weightFactors.verificationFactor * 100).toFixed(0)}% -
+ {accountSummary && ( +
+ {accountSummary.accountWeight.scope} + +
+ )}
+ {accountSummary && ( + <> +

{getWeightDescription(accountSummary.accountWeight.scope)}

+
+
+ 账号年龄 + + {accountSummary.accountWeight.ageWeight}% +
+
+ 活跃度 + + {accountSummary.accountWeight.activityWeigth}% +
+
+ 限制影响 + + {accountSummary.accountWeight.restrictWeight}% +
+
+ 实名认证 + + {accountSummary.accountWeight.realNameWeight}% +
+
+ + )} {/* 添加好友统计 */} @@ -701,29 +757,31 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri -
-
- 今日已添加 - {account.todayAdded} -
-
-
- 添加进度 - - {account.todayAdded}/{calculateMaxDailyAdds(account.accountWeight)} - + {accountSummary && ( +
+
+ 今日已添加 + {accountSummary.statistics.todayAdded} +
+
+
+ 添加进度 + + {accountSummary.statistics.todayAdded}/{accountSummary.statistics.addLimit} + +
+ +
+
+ 根据当前账号权重({accountSummary.accountWeight.scope}分),每日最多可添加{" "} + {accountSummary.statistics.addLimit}{" "} + 个好友
-
-
- 根据当前账号权重({account.accountWeight}分),每日最多可添加{" "} - {calculateMaxDailyAdds(account.accountWeight)}{" "} - 个好友 -
-
+ )} {/* 限制记录 */} @@ -733,20 +791,26 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri 限制记录
- setShowRestrictions(true)}> - 共 {account.restrictionRecords.length} 次 - + {accountSummary && ( + setShowRestrictions(true)}> + 共 {accountSummary.restrictions.length} 次 + + )}
-
- {account.restrictionRecords.slice(0, 2).map((record) => ( -
-
- {record.reason} - {record.date} + {accountSummary && ( +
+ {accountSummary.restrictions.slice(0, 2).map((record) => ( +
+
+ + {record.reason} + + {new Date(record.date).toLocaleDateString()} +
-
- ))} -
+ ))} +
+ )} diff --git a/Server/application/cunkebao/config/route.php b/Server/application/cunkebao/config/route.php index d53bf622..3df988aa 100644 --- a/Server/application/cunkebao/config/route.php +++ b/Server/application/cunkebao/config/route.php @@ -23,7 +23,7 @@ Route::group('v1/', function () { // 设备微信相关 Route::group('device/wechats', function () { Route::get('', 'app\cunkebao\controller\wechat\GetWechatsOnDevicesV1Controller@index'); // 获取在线微信账号列表 - Route::get(':id', 'app\cunkebao\controller\wechat\GetWechatOnDeviceSummarizeV1Controller@index'); // 获取微信号详情 + Route::get(':id/summary', 'app\cunkebao\controller\wechat\GetWechatOnDeviceSummarizeV1Controller@index'); // 获取微信号详情 Route::get('friends', 'app\cunkebao\controller\DeviceWechat@getFriends'); // 获取微信好友列表 Route::get('count', 'app\cunkebao\controller\DeviceWechat@count'); // 获取在线微信账号数量 diff --git a/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceSummarizeV1Controller.php b/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceSummarizeV1Controller.php index bd4feffd..282a024e 100644 --- a/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceSummarizeV1Controller.php +++ b/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceSummarizeV1Controller.php @@ -70,13 +70,13 @@ class GetWechatOnDeviceSummarizeV1Controller extends BaseController return [ [ 'id' => 1, - 'type' => 'warnnig', + 'level' => 2, 'reason' => '频繁添加好友', 'date' => date('Y-m-d H:i:s', strtotime('-1 day')), ], [ 'id' => 2, - 'type' => 'error', + 'level' => 3, 'reason' => '营销内容违规', 'date' => date('Y-m-d H:i:s', strtotime('-1 day')), ], @@ -228,7 +228,7 @@ class GetWechatOnDeviceSummarizeV1Controller extends BaseController protected function getStatistics(string $wechatId, array $accountWeight): array { return [ - 'addedCount' => $this->getTodayNewFriendCount($wechatId), + 'todayAdded' => $this->getTodayNewFriendCount($wechatId), 'addLimit' => $this->_calAllowedFriends($accountWeight['scope']) ]; } From 9498c9c47790d5bc4dfa5b7c393b26052a202560 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B3=E6=B8=85=E7=88=BD?= Date: Mon, 12 May 2025 12:01:07 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E7=A7=81=E5=9F=9F=E6=93=8D=E7=9B=98?= =?UTF-8?q?=E6=89=8B=20-=20=E8=B4=A6=E5=8F=B7=E6=9D=83=E9=87=8D=E8=AF=84?= =?UTF-8?q?=E4=BC=B0=E8=BF=9B=E5=BA=A6=E6=9D=A1=E5=AF=B9=E9=BD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cunkebao/app/wechat-accounts/[id]/page.tsx | 40 +++++++++++++--------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/Cunkebao/app/wechat-accounts/[id]/page.tsx b/Cunkebao/app/wechat-accounts/[id]/page.tsx index 9d594436..a5f7d89b 100644 --- a/Cunkebao/app/wechat-accounts/[id]/page.tsx +++ b/Cunkebao/app/wechat-accounts/[id]/page.tsx @@ -716,25 +716,33 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri <>

{getWeightDescription(accountSummary.accountWeight.scope)}

-
- 账号年龄 - - {accountSummary.accountWeight.ageWeight}% +
+ 账号年龄 +
+ +
+ {accountSummary.accountWeight.ageWeight}%
-
- 活跃度 - - {accountSummary.accountWeight.activityWeigth}% +
+ 活跃度 +
+ +
+ {accountSummary.accountWeight.activityWeigth}%
-
- 限制影响 - - {accountSummary.accountWeight.restrictWeight}% +
+ 限制影响 +
+ +
+ {accountSummary.accountWeight.restrictWeight}%
-
- 实名认证 - - {accountSummary.accountWeight.realNameWeight}% +
+ 实名认证 +
+ +
+ {accountSummary.accountWeight.realNameWeight}%
From 138e1c1deb51ead865340dcdeddcf0d2a02f6e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B3=E6=B8=85=E7=88=BD?= Date: Mon, 12 May 2025 13:57:24 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E7=A7=81=E5=9F=9F=E6=93=8D=E7=9B=98?= =?UTF-8?q?=E6=89=8B=20-=20=E5=BE=AE=E4=BF=A1=E5=8F=B7=E8=B4=A6=E5=8F=B7?= =?UTF-8?q?=E8=AF=A6=E6=83=85=E9=A1=B5=E9=9D=A2=E6=A0=B7=E5=BC=8F=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cunkebao/app/wechat-accounts/[id]/page.tsx | 38 ++++++++++++++++++---- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/Cunkebao/app/wechat-accounts/[id]/page.tsx b/Cunkebao/app/wechat-accounts/[id]/page.tsx index a5f7d89b..55d926ed 100644 --- a/Cunkebao/app/wechat-accounts/[id]/page.tsx +++ b/Cunkebao/app/wechat-accounts/[id]/page.tsx @@ -593,6 +593,30 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri setShowFriendDetail(true) } + // 修改获取限制等级颜色的函数 + const getRestrictionLevelColor = (level: string) => { + const colorMap = { + "1": "text-gray-600", + "2": "text-yellow-600", + "3": "text-red-600" + }; + return colorMap[level as keyof typeof colorMap] || "text-gray-600"; + } + + // 添加时间格式化函数 + const formatDateTime = (dateString: string) => { + const date = new Date(dateString); + return date.toLocaleString('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + hour12: false + }).replace(/\//g, '-'); + } + return ( {isLoading ? ( @@ -810,10 +834,10 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri {accountSummary.restrictions.slice(0, 2).map((record) => (
- + {record.reason} - {new Date(record.date).toLocaleDateString()} + {formatDateTime(record.date)}
))} @@ -938,13 +962,15 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri
- {account.restrictionRecords.map((record) => ( + {accountSummary && accountSummary.restrictions.map((record) => (
-
{record.reason}
- {record.date} +
+ {record.reason} +
+ {formatDateTime(record.date)}
-
恢复时间:{record.recoveryTime}
+
恢复时间:{formatDateTime(record.date)}
))}
From dbf6bb592a3cd0e54ab71514cfa1d150b6b921c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B3=E6=B8=85=E7=88=BD?= Date: Mon, 12 May 2025 15:32:42 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E5=AD=98=E5=AE=A2=E5=AE=9D=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E5=A5=BD=E5=8F=8B=E8=A1=A8=E6=9B=B4=E5=90=8D=EF=BC=8C?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E5=8A=A8=E6=80=81=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cunkebao/app/wechat-accounts/[id]/page.tsx | 27 ++-- Cunkebao/app/wechat-accounts/page.tsx | 5 +- ...{WechatFriend.php => WechatFriendShip.php} | 4 +- Server/application/cunkebao/config/route.php | 2 +- .../device/GetDeviceDetailV1Controller.php | 4 +- .../device/GetDeviceListV1Controller.php | 4 +- .../device/GetRelatedAccountsV1Controller.php | 4 +- .../friend/GetFriendListV1Controller.php | 4 +- .../GetWechatOnDeviceFriendsV1Controller.php | 129 ++++++++++++++++++ ...GetWechatOnDeviceSummarizeV1Controller.php | 14 +- .../GetWechatsOnDevicesV1Controller.php | 8 +- .../cunkebao/model/WechatFriend.php | 56 -------- .../GetCompanyDetailForProfileController.php | 2 +- .../GetCompanyDevicesForProfileController.php | 4 +- 14 files changed, 177 insertions(+), 90 deletions(-) rename Server/application/common/model/{WechatFriend.php => WechatFriendShip.php} (83%) create mode 100644 Server/application/cunkebao/controller/wechat/GetWechatOnDeviceFriendsV1Controller.php delete mode 100644 Server/application/cunkebao/model/WechatFriend.php diff --git a/Cunkebao/app/wechat-accounts/[id]/page.tsx b/Cunkebao/app/wechat-accounts/[id]/page.tsx index 55d926ed..bdb8945f 100644 --- a/Cunkebao/app/wechat-accounts/[id]/page.tsx +++ b/Cunkebao/app/wechat-accounts/[id]/page.tsx @@ -1,7 +1,8 @@ "use client" import { useState, useEffect, useRef, useCallback } from "react" -import { useRouter } from "next/navigation" +import * as React from "react" +import { useRouter, useParams } from "next/navigation" import { Card } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { @@ -136,8 +137,16 @@ interface WechatAccountSummary { }[]; } -export default function WechatAccountDetailPage({ params }: { params: { id: string } }) { +interface PageProps { + params: { + id: string + } +} + +export default function WechatAccountDetailPage() { const router = useRouter() + const params = useParams() + const id = params?.id as string const [account, setAccount] = useState(null) const [accountSummary, setAccountSummary] = useState(null) const [showRestrictions, setShowRestrictions] = useState(false) @@ -177,7 +186,7 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri const decodedData = JSON.parse(decodeURIComponent(dataParam)); setInitialData(decodedData); // 使用初始数据设置account - const mockData = generateMockAccountData(); + const mockData = generateMockAccountData(id); if (decodedData) { mockData.avatar = decodedData.avatar; mockData.nickname = decodedData.nickname; @@ -194,12 +203,12 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri } } else { // 如果没有初始数据,使用模拟数据 - const mockData = generateMockAccountData(); + const mockData = generateMockAccountData(id); setAccount(mockData); setFriendsTotal(mockData.friendCount); setIsLoading(false); } - }, []); + }, [id]); // 计算好友列表容器高度 const getFriendsContainerHeight = () => { @@ -212,7 +221,7 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri }; // 生成模拟账号数据(作为备用,服务器请求失败时使用) - const generateMockAccountData = (): WechatAccountDetail => { + const generateMockAccountData = (accountId: string): WechatAccountDetail => { // 生成随机标签 const generateRandomTags = (count: number): FriendTag[] => { const tagPool = [ @@ -288,7 +297,7 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri const friends = generateFriends(friendCount); const mockAccount: WechatAccountDetail = { - id: params.id, + id: accountId, avatar: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/img_v3_02jn_e7fcc2a4-3560-478d-911a-4ccd69c6392g.jpg-a8zVtwxMuSrPWN9dfWH93EBY0yM3Dh.jpeg", nickname: "卡若-25vig", @@ -490,7 +499,7 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri const fetchSummaryData = useCallback(async () => { try { setIsLoading(true); - const response = await fetchWechatAccountSummary(params.id); + const response = await fetchWechatAccountSummary(id); if (response.code === 200) { setAccountSummary(response.data); } else { @@ -510,7 +519,7 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri } finally { setIsLoading(false); } - }, [params.id]); + }, [id]); // 在页面加载和切换到概览标签时获取数据 useEffect(() => { diff --git a/Cunkebao/app/wechat-accounts/page.tsx b/Cunkebao/app/wechat-accounts/page.tsx index 7aacd973..71cefe92 100644 --- a/Cunkebao/app/wechat-accounts/page.tsx +++ b/Cunkebao/app/wechat-accounts/page.tsx @@ -279,7 +279,10 @@ export default function WechatAccountsPage() {

{account.nickname}

- + {account.status === "normal" ? "正常" : "异常"}
diff --git a/Server/application/common/model/WechatFriend.php b/Server/application/common/model/WechatFriendShip.php similarity index 83% rename from Server/application/common/model/WechatFriend.php rename to Server/application/common/model/WechatFriendShip.php index 5c121c82..1a6a0208 100644 --- a/Server/application/common/model/WechatFriend.php +++ b/Server/application/common/model/WechatFriendShip.php @@ -8,12 +8,12 @@ use think\model\concern\SoftDelete; /** * 微信好友模型类 */ -class WechatFriend extends Model +class WechatFriendShip extends Model { use SoftDelete; // 设置表名 - protected $name = 'wechat_friend'; + protected $name = 'wechat_friendship'; // 自动写入时间戳 protected $autoWriteTimestamp = true; diff --git a/Server/application/cunkebao/config/route.php b/Server/application/cunkebao/config/route.php index 3df988aa..25c7f477 100644 --- a/Server/application/cunkebao/config/route.php +++ b/Server/application/cunkebao/config/route.php @@ -24,8 +24,8 @@ Route::group('v1/', function () { Route::group('device/wechats', function () { Route::get('', 'app\cunkebao\controller\wechat\GetWechatsOnDevicesV1Controller@index'); // 获取在线微信账号列表 Route::get(':id/summary', 'app\cunkebao\controller\wechat\GetWechatOnDeviceSummarizeV1Controller@index'); // 获取微信号详情 + Route::get(':id/friends', 'app\cunkebao\controller\wechat\GetWechatOnDeviceFriendsV1Controller@index'); // 获取微信好友列表 - Route::get('friends', 'app\cunkebao\controller\DeviceWechat@getFriends'); // 获取微信好友列表 Route::get('count', 'app\cunkebao\controller\DeviceWechat@count'); // 获取在线微信账号数量 Route::get('device-count', 'app\cunkebao\controller\DeviceWechat@deviceCount'); // 获取有登录微信的设备数量 Route::put('refresh', 'app\cunkebao\controller\DeviceWechat@refresh'); // 刷新设备微信状态 diff --git a/Server/application/cunkebao/controller/device/GetDeviceDetailV1Controller.php b/Server/application/cunkebao/controller/device/GetDeviceDetailV1Controller.php index dbbfdff0..f1889f5e 100644 --- a/Server/application/cunkebao/controller/device/GetDeviceDetailV1Controller.php +++ b/Server/application/cunkebao/controller/device/GetDeviceDetailV1Controller.php @@ -7,7 +7,7 @@ use app\common\model\DeviceTaskconf as DeviceTaskconfModel; use app\common\model\DeviceUser as DeviceUserModel; use app\common\model\DeviceWechatLogin; use app\common\model\User as UserModel; -use app\common\model\WechatFriend; +use app\common\model\WechatFriendShip as WechatFriendShipModel; use app\cunkebao\controller\BaseController; use Eison\Utils\Helper\ArrHelper; use library\ResponseHelper; @@ -97,7 +97,7 @@ class GetDeviceDetailV1Controller extends BaseController $ownerWechatId = DeviceWechatLogin::where(compact('companyId', 'deviceId'))->order('createTime desc')->value('wechatId'); if ($ownerWechatId) { - return WechatFriend::where(['ownerWechatId' => $ownerWechatId])->count(); + return WechatFriendShipModel::where(['ownerWechatId' => $ownerWechatId])->count(); } return 0; diff --git a/Server/application/cunkebao/controller/device/GetDeviceListV1Controller.php b/Server/application/cunkebao/controller/device/GetDeviceListV1Controller.php index 787ba998..5862262e 100644 --- a/Server/application/cunkebao/controller/device/GetDeviceListV1Controller.php +++ b/Server/application/cunkebao/controller/device/GetDeviceListV1Controller.php @@ -5,7 +5,7 @@ namespace app\cunkebao\controller\device; use app\common\model\Device as DeviceModel; use app\common\model\DeviceUser as DeviceUserModel; use app\common\model\User as UserModel; -use app\common\model\WechatFriend as WechatFriendModel; +use app\common\model\WechatFriendShip as WechatFriendShipModel; use app\cunkebao\controller\BaseController; use library\ResponseHelper; @@ -105,7 +105,7 @@ class GetDeviceListV1Controller extends BaseController $sections = $item->toArray(); if ($item->wechatId) { - $sections['totalFriend'] = WechatFriendModel::where(['ownerWechatId' => $item->wechatId])->count(); + $sections['totalFriend'] = WechatFriendShipModel::where(['ownerWechatId' => $item->wechatId])->count(); } array_push($resultSets, $sections); diff --git a/Server/application/cunkebao/controller/device/GetRelatedAccountsV1Controller.php b/Server/application/cunkebao/controller/device/GetRelatedAccountsV1Controller.php index c2d09b16..e1d30b09 100644 --- a/Server/application/cunkebao/controller/device/GetRelatedAccountsV1Controller.php +++ b/Server/application/cunkebao/controller/device/GetRelatedAccountsV1Controller.php @@ -6,7 +6,7 @@ use app\common\model\DeviceUser as DeviceUserModel; use app\common\model\DeviceWechatLogin as DeviceWechatLoginModel; use app\common\model\User as UserModel; use app\common\model\WechatAccount as WechatAccountModel; -use app\common\model\WechatFriend; +use app\common\model\WechatFriendShip; use app\cunkebao\controller\BaseController; use library\ResponseHelper; @@ -110,7 +110,7 @@ class GetRelatedAccountsV1Controller extends BaseController */ protected function countFriend(string $wechatId): int { - return WechatFriend::where(['ownerWechatId' => $wechatId])->count(); + return WechatFriendShip::where(['ownerWechatId' => $wechatId])->count(); } /** diff --git a/Server/application/cunkebao/controller/friend/GetFriendListV1Controller.php b/Server/application/cunkebao/controller/friend/GetFriendListV1Controller.php index 7e3c0a64..a7e6de38 100644 --- a/Server/application/cunkebao/controller/friend/GetFriendListV1Controller.php +++ b/Server/application/cunkebao/controller/friend/GetFriendListV1Controller.php @@ -3,7 +3,7 @@ namespace app\cunkebao\controller\friend; use app\common\model\Device as DeviceModel; use app\common\model\DeviceUser as DeviceUserModel; -use app\common\model\WechatFriend; +use app\common\model\WechatFriendShip as WechatFriendShipModel; use app\cunkebao\controller\BaseController; use think\Db; @@ -42,7 +42,7 @@ class GetFriendListV1Controller extends BaseController } - $data = WechatFriend::alias('wf') + $data = WechatFriendShipModel::alias('wf') ->field(['wa1.nickname','wa1.avatar','wa1.alias','wf.id','wf.wechatId','wa2.nickname as ownerNickname','wa2.alias as ownerAlias','wa2.wechatId as ownerWechatId','wf.createTime']) ->Join('wechat_account wa1','wf.wechatId = wa1.wechatId') ->Join('wechat_account wa2','wf.ownerWechatId = wa2.wechatId') diff --git a/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceFriendsV1Controller.php b/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceFriendsV1Controller.php new file mode 100644 index 00000000..ebdc63b8 --- /dev/null +++ b/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceFriendsV1Controller.php @@ -0,0 +1,129 @@ +items() as $item) { + + + dd($item); + + $sections = $item->toArray() + []; + + array_push($resultSets, $sections); + } + + return $resultSets; + } + + /** + * 根据微信账号ID获取好友列表 + * + * @param array $where + * @return \think\Paginator 分页对象 + */ + protected function getFriendsByWechatIdAndQueryParams(array $where): \think\Paginator + { + $query = WechatFriendShipModel::alias('f') + ->field( + [ + 'w.id', 'w.nickname', 'w.avatar', + 'CASE WHEN w.alias IS NULL OR w.alias = "" THEN w.wechatId ELSE w.alias END AS wechatId', + 'f.memo', 'f.tags' + ] + ) + ->join('wechat_account w', 'w.wechatId = f.wechatId'); + + foreach ($where as $key => $value) { + if (is_numeric($key) && is_array($value) && isset($value[0]) && $value[0] === 'exp') { + $query->whereExp('', $value[1]); + continue; + } + + $query->where($key, $value); + } + + return $query->paginate($this->request->param('limit/d', 10), false, ['page' => $this->request->param('page/d', 1)]); + } + + /** + * 获取原始的64位的微信id + * + * @return string + * @throws \Exception + */ + protected function getStringWechatIdByNumberId(): string + { + $account = WechatAccountModel::find( + $this->request->param('id/d') + ); + + if (is_null($account)) { + throw new \Exception('微信账号不存在', 404); + } + + return 'udbfnvtk'; + + return $account->wechatId; + } + + /** + * 构建查询条件 + * + * @param array $params + * @return array + */ + protected function makeWhere(array $params = []): array + { + // 关键词搜索(同时搜索好友备注和标签) + if (!empty($keyword = $this->request->param('keyword'))) { + $where[] = ['exp', "f.memo LIKE '%{$keyword}%' OR f.tags LIKE '%{$keyword}%'"]; + } + + $where['f.ownerWechatId'] = $this->getStringWechatIdByNumberId(); + + return array_merge($where, $params); + } + + /** + * 获取微信好友列表 + * + * @return \think\response\Json + */ + public function index() + { + try { + $result = $this->getFriendsByWechatIdAndQueryParams( + $this->makeWhere() + ); + + return ResponseHelper::success( + [ + 'list' => $this->makeResultedSet($result), + 'total' => $result->total(), + ] + ); + } catch (\Exception $e) { + return ResponseHelper::error($e->getMessage(), $e->getCode()); + } + } +} \ No newline at end of file diff --git a/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceSummarizeV1Controller.php b/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceSummarizeV1Controller.php index 282a024e..0a086942 100644 --- a/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceSummarizeV1Controller.php +++ b/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceSummarizeV1Controller.php @@ -3,7 +3,7 @@ namespace app\cunkebao\controller\wechat; use app\common\model\WechatAccount as WechatAccountModel; -use app\common\model\WechatFriend as WechatFriendModel; +use app\common\model\WechatFriendShip as WechatFriendShipModel; use app\cunkebao\controller\BaseController; use library\ResponseHelper; @@ -208,7 +208,7 @@ class GetWechatOnDeviceSummarizeV1Controller extends BaseController */ protected function getTodayNewFriendCount(string $ownerWechatId): int { - return WechatFriendModel::where( compact('ownerWechatId') ) + return WechatFriendShipModel::where( compact('ownerWechatId') ) ->whereBetween('createTime', [ strtotime(date('Y-m-d 00:00:00')), @@ -239,9 +239,11 @@ class GetWechatOnDeviceSummarizeV1Controller extends BaseController * @return string * @throws \Exception */ - protected function getStringWechatId(): string + protected function getStringWechatIdByNumberId(): string { - $account = WechatAccountModel::find(333333); + $account = WechatAccountModel::find( + $this->request->param('id/d') + ); if (is_null($account)) { throw new \Exception('微信账号不存在', 404); @@ -258,9 +260,9 @@ class GetWechatOnDeviceSummarizeV1Controller extends BaseController public function index() { try { - // $wechatId = $this->getStringWechatId(); - $wechatId = '1111111'; + $wechatId = $this->getStringWechatIdByNumberId(); + // 以下内容依次加工数据 $accountAge = $this->getRegisterDate($wechatId); $activityLevel = $this->getActivityLevel($wechatId); $accountWeight = $this->getAccountWeight($wechatId); diff --git a/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php b/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php index 6f9cf715..db74b60c 100644 --- a/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php +++ b/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php @@ -8,7 +8,7 @@ use app\common\model\DeviceUser as DeviceUserModel; use app\common\model\DeviceWechatLogin as DeviceWechatLoginModel; use app\common\model\User as UserModel; use app\common\model\WechatAccount as WechatAccountModel; -use app\common\model\WechatFriend as WechatFriendModel; +use app\common\model\WechatFriendShip as WechatFriendShipModel; use app\cunkebao\controller\BaseController; use library\ResponseHelper; @@ -36,7 +36,7 @@ class GetWechatsOnDevicesV1Controller extends BaseController */ protected function getTodayNewFriendCount(string $ownerWechatId): int { - return WechatFriendModel::where( compact('ownerWechatId') ) + return WechatFriendShipModel::where( compact('ownerWechatId') ) ->whereBetween('createTime', [ strtotime(date('Y-m-d 00:00:00')), @@ -65,7 +65,7 @@ class GetWechatsOnDevicesV1Controller extends BaseController */ protected function getFriendsCount(string $ownerWechatId): int { - return WechatFriendModel::where(compact('ownerWechatId'))->count(); + return WechatFriendShipModel::where(compact('ownerWechatId'))->count(); } /** @@ -184,7 +184,7 @@ class GetWechatsOnDevicesV1Controller extends BaseController $where['w.wechatId'] = array('in', implode(',', $wechatIds)); - return array_merge($params, $where); + return array_merge($where, $params); } /** diff --git a/Server/application/cunkebao/model/WechatFriend.php b/Server/application/cunkebao/model/WechatFriend.php deleted file mode 100644 index b5a721ef..00000000 --- a/Server/application/cunkebao/model/WechatFriend.php +++ /dev/null @@ -1,56 +0,0 @@ -where('isDeleted', 0); - - // 添加筛选条件(昵称、备注、微信号、标签) - if (!empty($params['keyword'])) { - $keyword = $params['keyword']; - $query->where(function($q) use ($keyword) { - $q->whereOr('nickname', 'like', "%{$keyword}%") - ->whereOr('conRemark', 'like', "%{$keyword}%") - ->whereOr('alias', 'like', "%{$keyword}%") - ->whereOr("JSON_SEARCH(labels, 'one', '%{$keyword}%') IS NOT NULL"); - }); - } - - // 计算总数 - $total = $query->count(); - - // 分页查询数据 - $friends = $query->page($page, $limit) - ->order('createTime desc') - ->field('wechatId, alias, avatar, labels, accountNickname, accountRealName, nickname, conRemark, gender, region') - ->select(); - - return [ - 'list' => $friends, - 'total' => $total, - 'page' => $page, - 'limit' => $limit - ]; - } -} \ No newline at end of file diff --git a/Server/application/superadmin/controller/company/GetCompanyDetailForProfileController.php b/Server/application/superadmin/controller/company/GetCompanyDetailForProfileController.php index e878bb0d..787abd6b 100644 --- a/Server/application/superadmin/controller/company/GetCompanyDetailForProfileController.php +++ b/Server/application/superadmin/controller/company/GetCompanyDetailForProfileController.php @@ -6,7 +6,7 @@ use app\common\model\Company as CompanyModel; use app\common\model\Device as DeviceModel; use app\common\model\DeviceWechatLogin as DeviceWechatLoginModel; use app\common\model\User as UserModel; -use app\common\model\WechatFriend as WechatFriendModel; +use app\common\model\WechatFriendShip as WechatFriendModel; use app\superadmin\controller\BaseController; use library\ResponseHelper; diff --git a/Server/application/superadmin/controller/company/GetCompanyDevicesForProfileController.php b/Server/application/superadmin/controller/company/GetCompanyDevicesForProfileController.php index 810a6356..de71b5f9 100644 --- a/Server/application/superadmin/controller/company/GetCompanyDevicesForProfileController.php +++ b/Server/application/superadmin/controller/company/GetCompanyDevicesForProfileController.php @@ -4,7 +4,7 @@ namespace app\superadmin\controller\company; use app\common\model\Device as DeviceModel; use app\common\model\DeviceWechatLogin as DeviceWechatLoginModel; -use app\common\model\WechatFriend as WechatFriendModel; +use app\common\model\WechatFriendShip as WechatFriendShipModel; use Eison\Utils\Helper\ArrHelper; use library\ResponseHelper; use think\Controller; @@ -72,7 +72,7 @@ class GetCompanyDevicesForProfileController extends Controller $relations = $this->getDeviceWechatRelationsByDeviceIds($deviceIds); // 统计微信好友数量 - $friendCounts = WechatFriendModel::alias('f') + $friendCounts = WechatFriendShipModel::alias('f') ->field([ 'f.ownerWechatId wechatId', 'count(*) friendCount' ]) From 434e8deca696ee2b07f2d598c15403ebc57ab784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B3=E6=B8=85=E7=88=BD?= Date: Mon, 12 May 2025 16:29:23 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E7=A7=81=E5=9F=9F=E6=93=8D=E7=9B=98?= =?UTF-8?q?=E6=89=8B=20-=20=E5=BE=AE=E4=BF=A1=E5=8F=B7=E8=AF=A6=E6=83=85/?= =?UTF-8?q?=E5=A5=BD=E5=8F=8B=E5=88=97=E8=A1=A8=E5=8A=9F=E8=83=BD=E8=BF=94?= =?UTF-8?q?=E5=B7=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wechat/GetWechatOnDeviceFriendsV1Controller.php | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceFriendsV1Controller.php b/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceFriendsV1Controller.php index ebdc63b8..622e7899 100644 --- a/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceFriendsV1Controller.php +++ b/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceFriendsV1Controller.php @@ -23,13 +23,8 @@ class GetWechatOnDeviceFriendsV1Controller extends Controller $resultSets = []; foreach ($result->items() as $item) { - - - dd($item); - - $sections = $item->toArray() + []; - - array_push($resultSets, $sections); + $item->tags = json_decode($item->tags); + array_push($resultSets, $item->toArray()); } return $resultSets; @@ -81,8 +76,6 @@ class GetWechatOnDeviceFriendsV1Controller extends Controller throw new \Exception('微信账号不存在', 404); } - return 'udbfnvtk'; - return $account->wechatId; } From 6e4f4e72db4b777d25393699e229603e0ca2c6a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B3=E6=B8=85=E7=88=BD?= Date: Mon, 12 May 2025 16:51:57 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E7=A7=81=E5=9F=9F=E6=93=8D=E7=9B=98?= =?UTF-8?q?=E6=89=8B=20-=20=E5=AF=B9=E6=8E=A5=E5=BE=AE=E4=BF=A1=E5=8F=B7?= =?UTF-8?q?=E8=AF=A6=E6=83=85/=E5=A5=BD=E5=8F=8B=E5=88=97=E8=A1=A8=20?= =?UTF-8?q?=E5=8F=8A=20=E9=A1=B5=E9=9D=A2=E7=BB=86=E8=8A=82=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cunkebao/app/wechat-accounts/[id]/page.tsx | 133 ++++++++++++--------- 1 file changed, 75 insertions(+), 58 deletions(-) diff --git a/Cunkebao/app/wechat-accounts/[id]/page.tsx b/Cunkebao/app/wechat-accounts/[id]/page.tsx index bdb8945f..fab42f78 100644 --- a/Cunkebao/app/wechat-accounts/[id]/page.tsx +++ b/Cunkebao/app/wechat-accounts/[id]/page.tsx @@ -1,10 +1,18 @@ "use client" import { useState, useEffect, useRef, useCallback } from "react" -import * as React from "react" -import { useRouter, useParams } from "next/navigation" +import { useParams } from "next/navigation" +import { useRouter } from "next/navigation" +import { api } from "@/lib/api" +import { fetchWechatAccountSummary } from "@/api/wechat-accounts" import { Card } from "@/components/ui/card" import { Button } from "@/components/ui/button" +import { Badge } from "@/components/ui/badge" +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" +import { Progress } from "@/components/ui/progress" +import { Input } from "@/components/ui/input" +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" +import { toast } from "@/components/ui/use-toast" import { ChevronLeft, Smartphone, @@ -21,11 +29,6 @@ import { ChevronRight, Loader2, } from "lucide-react" -import { Badge } from "@/components/ui/badge" -import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" -import { Progress } from "@/components/ui/progress" -import { Input } from "@/components/ui/input" -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { Dialog, DialogContent, @@ -44,8 +47,25 @@ import { PaginationNext, PaginationPrevious, } from "@/components/ui/pagination" -import { toast } from "@/components/ui/use-toast" -import { fetchWechatFriends, fetchWechatAccountSummary } from "@/api/wechat-accounts" +import { fetchWechatFriends } from "@/api/wechat-accounts" + +interface ApiResponse { + code: number; + msg: string; + data: T; +} + +interface FriendsResponse { + list: Array<{ + id: number; + nickname: string; + avatar: string; + wechatId: string; + memo: string; + tags: string[]; + }>; + total: number; +} interface RestrictionRecord { id: string @@ -61,18 +81,22 @@ interface FriendTag { color: string } -interface WechatFriend { - id: string - avatar: string - nickname: string - wechatId: string - remark: string - addTime: string - lastInteraction: string - tags: FriendTag[] - region: string - source: string - notes: string +interface Friend { + id: string; + avatar: string; + nickname: string; + wechatId: string; + remark: string; + addTime: string; + lastInteraction: string; + tags: Array<{ + id: string; + name: string; + color: string; + }>; + region: string; + source: string; + notes: string; } interface WechatAccountDetail { @@ -109,7 +133,7 @@ interface WechatAccountDetail { friends: number messages: number }[] - friends: WechatFriend[] + friends: Friend[] } interface WechatAccountSummary { @@ -152,13 +176,13 @@ export default function WechatAccountDetailPage() { const [showRestrictions, setShowRestrictions] = useState(false) const [showTransferConfirm, setShowTransferConfirm] = useState(false) const [showFriendDetail, setShowFriendDetail] = useState(false) - const [selectedFriend, setSelectedFriend] = useState(null) + const [selectedFriend, setSelectedFriend] = useState(null) const [searchQuery, setSearchQuery] = useState("") const [activeTab, setActiveTab] = useState("overview") const [isLoading, setIsLoading] = useState(false) // 好友列表相关状态 - const [friends, setFriends] = useState([]) + const [friends, setFriends] = useState([]) const [friendsPage, setFriendsPage] = useState(1) const [friendsTotal, setFriendsTotal] = useState(0) const [hasMoreFriends, setHasMoreFriends] = useState(true) @@ -249,7 +273,7 @@ export default function WechatAccountDetailPage() { // 生成随机好友 const friendCount = Math.floor(Math.random() * (300 - 150)) + 150; - const generateFriends = (count: number): WechatFriend[] => { + const generateFriends = (count: number): Friend[] => { return Array.from({ length: count }, (_, i) => { const firstName = ["张", "王", "李", "赵", "陈", "刘", "杨", "黄", "周", "吴"][Math.floor(Math.random() * 10)]; const secondName = ["小", "大", "明", "华", "强", "伟", "芳", "娜", "秀", "英"][ @@ -364,7 +388,7 @@ export default function WechatAccountDetailPage() { return colors[Math.floor(Math.random() * colors.length)]; }; - // 获取好友列表数据 + // 修改fetchFriends函数 const fetchFriends = useCallback(async (page: number = 1, isNewSearch: boolean = false) => { if (!account || isFetchingFriends) return; @@ -372,30 +396,29 @@ export default function WechatAccountDetailPage() { setIsFetchingFriends(true); setHasFriendLoadError(false); - // 调用API获取好友列表 - const response = await fetchWechatFriends(account.wechatId, page, 20, searchQuery); + const data = await api.get>(`/v1/device/wechats/${id}/friends?page=${page}&limit=30`, true); - if (response && response.code === 200) { - // 更新总数计数,确保在第一次加载时设置 + if (data && data.code === 200) { + // 更新总数计数 if (isNewSearch || friendsTotal === 0) { - setFriendsTotal(response.data.total || 0); + setFriendsTotal(data.data.total || 0); } - const newFriends = response.data.list.map((friend: any) => ({ - id: friend.wechatId, + const newFriends = data.data.list.map((friend) => ({ + id: friend.id.toString(), avatar: friend.avatar, - nickname: friend.nickname || '未设置昵称', + nickname: friend.nickname, wechatId: friend.wechatId, - remark: friend.remark || '', + remark: friend.memo || '', addTime: '2024-01-01', // 接口未返回,使用默认值 lastInteraction: '2024-01-01', // 接口未返回,使用默认值 - tags: (friend.labels || []).map((label: string, index: number) => ({ + tags: (friend.tags || []).map((label: string, index: number) => ({ id: `tag-${index}`, name: label, color: getRandomTagColor(), })), - region: friend.region || '未知地区', - source: '微信好友', // 接口未返回,使用默认值 + region: '未知地区', + source: '微信好友', notes: '', })); @@ -408,14 +431,13 @@ export default function WechatAccountDetailPage() { setFriendsPage(page); // 判断是否还有更多数据 - setHasMoreFriends(page * 20 < response.data.total); + setHasMoreFriends(page * 30 < data.data.total); - console.log("好友列表加载成功,总数:", response.data.total); } else { setHasFriendLoadError(true); toast({ title: "获取好友列表失败", - description: response?.msg || "请稍后再试", + description: data?.msg || "请稍后再试", variant: "destructive" }); } @@ -430,7 +452,7 @@ export default function WechatAccountDetailPage() { } finally { setIsFetchingFriends(false); } - }, [account, searchQuery, friendsTotal]); + }, [account, id, friendsTotal]); // 处理搜索 const handleSearch = useCallback(() => { @@ -441,11 +463,14 @@ export default function WechatAccountDetailPage() { }, [fetchFriends]); // 处理标签切换 - useEffect(() => { - if (account && friends.length === 0) { + const handleTabChange = (value: string) => { + setActiveTab(value); + if (value === "overview") { + fetchSummaryData(); + } else if (value === "friends" && friends.length === 0) { fetchFriends(1, true); } - }, [account, friends.length, fetchFriends]); + }; // 设置IntersectionObserver用于懒加载 useEffect(() => { @@ -535,14 +560,6 @@ export default function WechatAccountDetailPage() { } }, [fetchSummaryData, activeTab]); - // 处理标签切换 - const handleTabChange = (value: string) => { - setActiveTab(value); - if (value === "overview") { - fetchSummaryData(); - } - }; - if (!account) { return
加载中...
} @@ -597,7 +614,7 @@ export default function WechatAccountDetailPage() { setShowTransferConfirm(false) } - const handleFriendClick = (friend: WechatFriend) => { + const handleFriendClick = (friend: Friend) => { setSelectedFriend(friend) setShowFriendDetail(true) } @@ -633,7 +650,7 @@ export default function WechatAccountDetailPage() {
) : account ? ( -
+