From 227fcae39de634238e13140a5e3a7a749773c125 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Fri, 14 Nov 2025 18:19:08 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cunkebao/controller/StatsController.php | 168 ++++++++----- .../plan/GetPlanSceneListV1Controller.php | 184 ++++++++++++-- .../controller/plan/PlanSceneV1Controller.php | 82 +++++-- .../GetWechatsOnDevicesV1Controller.php | 230 +++++++++--------- 4 files changed, 448 insertions(+), 216 deletions(-) diff --git a/Server/application/cunkebao/controller/StatsController.php b/Server/application/cunkebao/controller/StatsController.php index a47f80c8..a6abd115 100644 --- a/Server/application/cunkebao/controller/StatsController.php +++ b/Server/application/cunkebao/controller/StatsController.php @@ -25,13 +25,18 @@ class StatsController extends Controller */ public function baseInfoStats() { - $deviceNum = Db::name('device')->where(['companyId' => $this->request->userInfo['companyId'], 'deleteTime' => 0])->count(); - $wechatNum = Db::name('wechat_customer')->where(['companyId' => $this->request->userInfo['companyId']])->count(); - $aliveWechatNum = Db::name('wechat_customer')->alias('wc') - ->join('device_wechat_login dwl', 'wc.wechatId = dwl.wechatId') - ->where(['wc.companyId' => $this->request->userInfo['companyId'], 'dwl.alive' => 1]) - ->group('wc.wechatId') - ->count(); + + $where = [ + ['departmentId','=',$this->request->userInfo['companyId']] + ]; + if (!empty($this->request->userInfo['isAdmin'])){ + $where[] = ['id','=',$this->request->userInfo['s2_accountId']]; + } + $accounts = Db::table('s2_company_account')->where($where)->column('id'); + + $deviceNum = Db::table('s2_device')->whereIn('currentAccountId',$accounts)->where(['isDeleted' => 0])->count(); + $wechatNum = Db::table('s2_wechat_account')->whereIn('deviceAccountId',$accounts)->count(); + $aliveWechatNum = Db::table('s2_wechat_account')->whereIn('deviceAccountId',$accounts)->where(['wechatAlive' => 1])->count(); $data = [ 'deviceNum' => $deviceNum, 'wechatNum' => $wechatNum, @@ -58,29 +63,50 @@ class StatsController extends Controller ->page(1, $num) ->select(); - foreach ($planScene as &$v) { - $allNum = Db::name('customer_acquisition_task')->alias('ac') - ->join('task_customer tc', 'tc.task_id = ac.id') - ->where(['ac.sceneId' => $v['id'], 'ac.companyId' => $this->request->userInfo['companyId'], 'ac.deleteTime' => 0]) - ->count(); - - $addNum = Db::name('customer_acquisition_task')->alias('ac') - ->join('task_customer tc', 'tc.task_id = ac.id') - ->where(['ac.sceneId' => $v['id'], 'ac.companyId' => $this->request->userInfo['companyId'], 'ac.deleteTime' => 0]) - ->whereIn('tc.status', [1, 2, 3, 4]) - ->count(); - - $passNum = Db::name('customer_acquisition_task')->alias('ac') - ->join('task_customer tc', 'tc.task_id = ac.id') - ->where(['ac.sceneId' => $v['id'], 'ac.companyId' => $this->request->userInfo['companyId'], 'ac.deleteTime' => 0]) - ->whereIn('tc.status', [4]) - ->count(); - - $v['allNum'] = $allNum; - $v['addNum'] = $addNum; - $v['passNum'] = $passNum; + if (empty($planScene)) { + return successJson([], '获取成功'); } - unset($v); + + $sceneIds = array_column($planScene, 'id'); + $companyId = $this->request->userInfo['companyId']; + + $stats = Db::name('customer_acquisition_task')->alias('ac') + ->join('task_customer tc', 'tc.task_id = ac.id') + ->where([ + ['ac.companyId', '=', $companyId], + ['ac.deleteTime', '=', 0], + ['ac.sceneId', 'in', $sceneIds], + ]) + ->field([ + 'ac.sceneId', + Db::raw('COUNT(1) as allNum'), + Db::raw("SUM(CASE WHEN tc.status IN (1,2,3,4) THEN 1 ELSE 0 END) as addNum"), + Db::raw("SUM(CASE WHEN tc.status = 4 THEN 1 ELSE 0 END) as passNum"), + ]) + ->group('ac.sceneId') + ->select(); + + $statsMap = []; + foreach ($stats as $row) { + $sceneId = is_array($row) ? ($row['sceneId'] ?? 0) : ($row->sceneId ?? 0); + if (!$sceneId) { + continue; + } + $statsMap[$sceneId] = [ + 'allNum' => (int)(is_array($row) ? ($row['allNum'] ?? 0) : ($row->allNum ?? 0)), + 'addNum' => (int)(is_array($row) ? ($row['addNum'] ?? 0) : ($row->addNum ?? 0)), + 'passNum' => (int)(is_array($row) ? ($row['passNum'] ?? 0) : ($row->passNum ?? 0)), + ]; + } + + foreach ($planScene as &$item) { + $sceneStats = $statsMap[$item['id']] ?? ['allNum' => 0, 'addNum' => 0, 'passNum' => 0]; + $item['allNum'] = $sceneStats['allNum']; + $item['addNum'] = $sceneStats['addNum']; + $item['passNum'] = $sceneStats['passNum']; + } + unset($item); + return successJson($planScene, '获取成功'); } @@ -150,44 +176,62 @@ class StatsController extends Controller $companyId = $this->request->userInfo['companyId']; $days = 7; - $dates = []; + $endTime = strtotime(date('Y-m-d 23:59:59')); + $startTime = strtotime(date('Y-m-d 00:00:00', strtotime('-' . ($days - 1) . ' day'))); + + $dateMap = []; + $dateLabels = []; + for ($i = 0; $i < $days; $i++) { + $currentDate = date('Y-m-d', strtotime("-" . ($days - 1 - $i) . " day")); + $weekIndex = date("w", strtotime($currentDate)); + $dateMap[$currentDate] = self::WEEK[$weekIndex]; + $dateLabels[] = self::WEEK[$weekIndex]; + } + + $baseWhere = [ + ['ac.companyId', '=', $companyId], + ['ac.deleteTime', '=', 0], + ]; + + $fetchCounts = function (string $timeField, array $status = []) use ($baseWhere, $startTime, $endTime) { + $query = Db::name('customer_acquisition_task')->alias('ac') + ->join('task_customer tc', 'tc.task_id = ac.id') + ->where($baseWhere) + ->whereBetween('tc.' . $timeField, [$startTime, $endTime]); + if (!empty($status)) { + $query->whereIn('tc.status', $status); + } + $rows = $query->field([ + "FROM_UNIXTIME(tc.{$timeField}, '%Y-%m-%d')" => 'day', + 'COUNT(1)' => 'total' + ])->group('day')->select(); + + $result = []; + foreach ($rows as $row) { + $day = is_array($row) ? ($row['day'] ?? '') : ($row->day ?? ''); + $total = (int)(is_array($row) ? ($row['total'] ?? 0) : ($row->total ?? 0)); + if ($day) { + $result[$day] = $total; + } + } + return $result; + }; + + $allNumDict = $fetchCounts('createTime'); + $addNumDict = $fetchCounts('updateTime', [1, 2, 3, 4]); + $passNumDict = $fetchCounts('updateTime', [4]); + $allNum = []; $addNum = []; $passNum = []; - - for ($i = $days - 1; $i >= 0; $i--) { - $date = date('Y-m-d', strtotime("-$i day")); - $start = strtotime($date . ' 00:00:00'); - $end = strtotime($date . ' 23:59:59'); - - // 获客总量 - $allNum[] = Db::name('customer_acquisition_task')->alias('ac') - ->join('task_customer tc', 'tc.task_id = ac.id') - ->where(['ac.companyId' => $companyId, 'ac.deleteTime' => 0]) - ->where('tc.createTime', 'between', [$start, $end]) - ->count(); - - // 添加量 - $addNum[] = Db::name('customer_acquisition_task')->alias('ac') - ->join('task_customer tc', 'tc.task_id = ac.id') - ->where(['ac.companyId' => $companyId, 'ac.deleteTime' => 0]) - ->where('tc.updateTime', 'between', [$start, $end]) - ->whereIn('tc.status', [1, 2, 3, 4]) - ->count(); - - // 通过量 - $passNum[] = Db::name('customer_acquisition_task')->alias('ac') - ->join('task_customer tc', 'tc.task_id = ac.id') - ->where(['ac.companyId' => $companyId, 'ac.deleteTime' => 0]) - ->where('tc.updateTime', 'between', [$start, $end]) - ->whereIn('tc.status', [4]) - ->count(); - - $week = date("w", strtotime($date)); - $dates[] = self::WEEK[$week]; + foreach (array_keys($dateMap) as $dateKey) { + $allNum[] = $allNumDict[$dateKey] ?? 0; + $addNum[] = $addNumDict[$dateKey] ?? 0; + $passNum[] = $passNumDict[$dateKey] ?? 0; } + $data = [ - 'date' => $dates, + 'date' => $dateLabels, 'allNum' => $allNum, 'addNum' => $addNum, 'passNum' => $passNum, diff --git a/Server/application/cunkebao/controller/plan/GetPlanSceneListV1Controller.php b/Server/application/cunkebao/controller/plan/GetPlanSceneListV1Controller.php index ef71e4c6..cc8c6fbe 100644 --- a/Server/application/cunkebao/controller/plan/GetPlanSceneListV1Controller.php +++ b/Server/application/cunkebao/controller/plan/GetPlanSceneListV1Controller.php @@ -38,17 +38,23 @@ class GetPlanSceneListV1Controller extends BaseController // 查询数据 $query = PlansSceneModel::where($where); - // 获取总数 - $total = $query->count(); - // 获取分页数据 $list = $query->order('sort DESC')->select()->toArray(); + + if (empty($list)) { + return []; + } + + $sceneIds = array_column($list, 'id'); + $companyId = $this->getUserInfo('companyId'); + $statsMap = $this->buildSceneStats($sceneIds, (int)$companyId); // 处理数据 foreach($list as &$val) { - $val['scenarioTags'] = json_decode($val['scenarioTags'], true); - $val['count'] = $this->getPlanCount($val['id']); - $val['growth'] = $this->calculateGrowth($val['id']); + $val['scenarioTags'] = json_decode($val['scenarioTags'], true) ?: []; + $sceneStats = $statsMap[$val['id']] ?? ['count' => 0, 'growth' => '0%']; + $val['count'] = $sceneStats['count']; + $val['growth'] = $sceneStats['growth']; } unset($val); @@ -97,7 +103,7 @@ class GetPlanSceneListV1Controller extends BaseController return ResponseHelper::error('场景不存在'); } - $data['scenarioTags'] = json_decode($data['scenarioTags'], true); + $data['scenarioTags'] = json_decode($data['scenarioTags'], true) ?: []; $data['count'] = $this->getPlanCount($id); $data['growth'] = $this->calculateGrowth($id); @@ -130,27 +136,151 @@ class GetPlanSceneListV1Controller extends BaseController */ private function calculateGrowth(int $sceneId): string { - // 获取本月和上月的计划数量 - $currentMonth = Db::name('customer_acquisition_task') - ->where('sceneId', $sceneId) - ->where('status', 1) - ->whereTime('createTime', '>=', strtotime(date('Y-m-01'))) - ->count(); - - $lastMonth = Db::name('customer_acquisition_task') - ->where('sceneId', $sceneId) - ->where('status', 1) - ->whereTime('createTime', 'between', [ - strtotime(date('Y-m-01', strtotime('-1 month'))), - strtotime(date('Y-m-01')) - 1 - ]) - ->count(); - - if ($lastMonth == 0) { - return $currentMonth > 0 ? '100%' : '0%'; + $companyId = $this->getUserInfo('companyId'); + $currentStart = strtotime(date('Y-m-01 00:00:00')); + $nextMonthStart = strtotime(date('Y-m-01 00:00:00', strtotime('+1 month'))); + $lastMonthStart = strtotime(date('Y-m-01 00:00:00', strtotime('-1 month'))); + + $currentMonth = $this->getSceneMonthlyCount($sceneId, $companyId, $currentStart, $nextMonthStart - 1); + $lastMonth = $this->getSceneMonthlyCount($sceneId, $companyId, $lastMonthStart, $currentStart - 1); + + return $this->formatGrowthPercentage($currentMonth, $lastMonth); + } + + /** + * 批量构建场景统计数据 + * @param array $sceneIds + * @param int $companyId + * @return array + */ + private function buildSceneStats(array $sceneIds, int $companyId): array + { + if (empty($sceneIds)) { + return []; } - - $growth = round(($currentMonth - $lastMonth) / $lastMonth * 100, 2); + + $totalCounts = $this->getSceneTaskCounts($sceneIds, $companyId); + + $currentStart = strtotime(date('Y-m-01 00:00:00')); + $nextMonthStart = strtotime(date('Y-m-01 00:00:00', strtotime('+1 month'))); + $lastMonthStart = strtotime(date('Y-m-01 00:00:00', strtotime('-1 month'))); + + $currentMonthCounts = $this->getSceneMonthlyCounts($sceneIds, $companyId, $currentStart, $nextMonthStart - 1); + $lastMonthCounts = $this->getSceneMonthlyCounts($sceneIds, $companyId, $lastMonthStart, $currentStart - 1); + + $stats = []; + foreach ($sceneIds as $sceneId) { + $current = $currentMonthCounts[$sceneId] ?? 0; + $last = $lastMonthCounts[$sceneId] ?? 0; + $stats[$sceneId] = [ + 'count' => $totalCounts[$sceneId] ?? 0, + 'growth' => $this->formatGrowthPercentage($current, $last), + ]; + } + + return $stats; + } + + /** + * 获取场景计划总数 + * @param array $sceneIds + * @param int $companyId + * @return array + */ + private function getSceneTaskCounts(array $sceneIds, int $companyId): array + { + if (empty($sceneIds)) { + return []; + } + + $rows = Db::name('customer_acquisition_task') + ->whereIn('sceneId', $sceneIds) + ->where('companyId', $companyId) + ->where('deleteTime', 0) + ->field('sceneId, COUNT(*) as total') + ->group('sceneId') + ->select(); + + $result = []; + foreach ($rows as $row) { + $sceneId = is_array($row) ? ($row['sceneId'] ?? 0) : ($row->sceneId ?? 0); + if (!$sceneId) { + continue; + } + $result[$sceneId] = (int)(is_array($row) ? ($row['total'] ?? 0) : ($row->total ?? 0)); + } + + return $result; + } + + /** + * 获取场景月度数据 + * @param array $sceneIds + * @param int $companyId + * @param int $startTime + * @param int $endTime + * @return array + */ + private function getSceneMonthlyCounts(array $sceneIds, int $companyId, int $startTime, int $endTime): array + { + if (empty($sceneIds)) { + return []; + } + + $rows = Db::name('customer_acquisition_task') + ->whereIn('sceneId', $sceneIds) + ->where('companyId', $companyId) + ->where('status', 1) + ->where('deleteTime', 0) + ->whereBetween('createTime', [$startTime, $endTime]) + ->field('sceneId, COUNT(*) as total') + ->group('sceneId') + ->select(); + + $result = []; + foreach ($rows as $row) { + $sceneId = is_array($row) ? ($row['sceneId'] ?? 0) : ($row->sceneId ?? 0); + if (!$sceneId) { + continue; + } + $result[$sceneId] = (int)(is_array($row) ? ($row['total'] ?? 0) : ($row->total ?? 0)); + } + + return $result; + } + + /** + * 获取单个场景的月度数据 + * @param int $sceneId + * @param int $companyId + * @param int $startTime + * @param int $endTime + * @return int + */ + private function getSceneMonthlyCount(int $sceneId, int $companyId, int $startTime, int $endTime): int + { + return Db::name('customer_acquisition_task') + ->where('sceneId', $sceneId) + ->where('companyId', $companyId) + ->where('status', 1) + ->where('deleteTime', 0) + ->whereBetween('createTime', [$startTime, $endTime]) + ->count(); + } + + /** + * 计算增长百分比 + * @param int $current + * @param int $last + * @return string + */ + private function formatGrowthPercentage(int $current, int $last): string + { + if ($last == 0) { + return $current > 0 ? '100%' : '0%'; + } + + $growth = round(($current - $last) / $last * 100, 2); return $growth . '%'; } } \ No newline at end of file diff --git a/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php b/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php index c71643ee..75d1d01e 100644 --- a/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php +++ b/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php @@ -50,29 +50,35 @@ class PlanSceneV1Controller extends BaseController ->page($page, $limit) ->select(); + if (!empty($list)) { + $taskIds = array_column($list, 'id'); + $statsMap = $this->buildTaskStats($taskIds); + foreach($list as &$val){ - $val['createTime'] = date('Y-m-d H:i:s', $val['createTime']); - $val['updateTime'] = date('Y-m-d H:i:s', $val['updateTime']); - $val['sceneConf'] = json_decode($val['sceneConf'],true); - $val['reqConf'] = json_decode($val['reqConf'],true); - $val['msgConf'] = json_decode($val['msgConf'],true); - $val['tagConf'] = json_decode($val['tagConf'],true); - - $val['acquiredCount'] = Db::name('task_customer')->where('task_id',$val['id'])->count(); - $val['addedCount'] = Db::name('task_customer')->where('task_id',$val['id'])->whereIn('status',[1,2,3,4])->count(); - $val['passCount'] = Db::name('task_customer')->where('task_id',$val['id'])->where('status',4)->count(); - $val['passRate'] = 0; - if(!empty($val['passCount']) && !empty($val['addedCount'])){ - $passRate = ($val['passCount'] / $val['addedCount']) * 100; - $val['passRate'] = number_format($passRate,2); - } - - $lastTime = Db::name('task_customer')->where(['task_id'=>$val['id']])->max('updateTime'); - $val['lastUpdated'] = !empty($lastTime) ? date('Y-m-d H:i', $lastTime) : '--'; + $val['createTime'] = !empty($val['createTime']) ? date('Y-m-d H:i:s', $val['createTime']) : ''; + $val['updateTime'] = !empty($val['updateTime']) ? date('Y-m-d H:i:s', $val['updateTime']) : ''; + $val['sceneConf'] = json_decode($val['sceneConf'],true) ?: []; + $val['reqConf'] = json_decode($val['reqConf'],true) ?: []; + $val['msgConf'] = json_decode($val['msgConf'],true) ?: []; + $val['tagConf'] = json_decode($val['tagConf'],true) ?: []; + $stats = $statsMap[$val['id']] ?? [ + 'acquiredCount' => 0, + 'addedCount' => 0, + 'passCount' => 0, + 'lastUpdated' => 0 + ]; + $val['acquiredCount'] = $stats['acquiredCount']; + $val['addedCount'] = $stats['addedCount']; + $val['passCount'] = $stats['passCount']; + $val['passRate'] = ($stats['addedCount'] > 0 && $stats['passCount'] > 0) + ? number_format(($stats['passCount'] / $stats['addedCount']) * 100, 2) + : 0; + $val['lastUpdated'] = !empty($stats['lastUpdated']) ? date('Y-m-d H:i', $stats['lastUpdated']) : '--'; } unset($val); + } return ResponseHelper::success([ 'total' => $total, 'list' => $list @@ -383,6 +389,46 @@ class PlanSceneV1Controller extends BaseController ]; } + /** + * 构建任务统计 + * @param array $taskIds + * @return array + */ + private function buildTaskStats(array $taskIds): array + { + if (empty($taskIds)) { + return []; + } + + $rows = Db::name('task_customer') + ->whereIn('task_id', $taskIds) + ->field([ + 'task_id as taskId', + 'COUNT(1) as acquiredCount', + "SUM(CASE WHEN status IN (1,2,3,4) THEN 1 ELSE 0 END) as addedCount", + "SUM(CASE WHEN status = 4 THEN 1 ELSE 0 END) as passCount", + 'MAX(updateTime) as lastUpdated' + ]) + ->group('task_id') + ->select(); + + $stats = []; + foreach ($rows as $row) { + $taskId = is_array($row) ? ($row['taskId'] ?? 0) : ($row->taskId ?? 0); + if (!$taskId) { + continue; + } + $stats[$taskId] = [ + 'acquiredCount' => (int)(is_array($row) ? ($row['acquiredCount'] ?? 0) : ($row->acquiredCount ?? 0)), + 'addedCount' => (int)(is_array($row) ? ($row['addedCount'] ?? 0) : ($row->addedCount ?? 0)), + 'passCount' => (int)(is_array($row) ? ($row['passCount'] ?? 0) : ($row->passCount ?? 0)), + 'lastUpdated' => (int)(is_array($row) ? ($row['lastUpdated'] ?? 0) : ($row->lastUpdated ?? 0)), + ]; + } + + return $stats; + } + /** * 获取微信小程序码 diff --git a/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php b/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php index 05ac93ca..177d67a6 100644 --- a/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php +++ b/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php @@ -19,92 +19,6 @@ use think\Db; */ class GetWechatsOnDevicesV1Controller extends BaseController { - /** - * 计算今日可添加好友数量 - * - * @param string $wechatId - * @return int - */ - protected function getCanAddFriendCount(string $wechatId): int - { - $weight = (string)WechatCustomerModel::where( - [ - 'wechatId' => $wechatId, - 'companyId' => $this->getUserInfo('companyId') - ] - ) - ->value('weight'); - - return json_decode($weight)->addLimit ?? 0; - } - - /** - * 计算今日新增好友数量 - * - * @param string $ownerWechatId - * @return int - */ - protected function getTodayNewFriendCount(string $ownerWechatId): int - { - return WechatFriendShipModel::where(compact('ownerWechatId')) - ->whereBetween('createTime', - [ - strtotime(date('Y-m-d 00:00:00')), - strtotime(date('Y-m-d 23:59:59')) - ] - ) - ->count('*'); - } - - /** - * TODO 获取微信加友状态 - * - * @param string $wechatId - * @return int - */ - protected function getWechatAddFriendStatus(string $wechatId): int - { - return Db::name('device_wechat_login')->where(['wechatId' => $wechatId])->order('id DESC')->value('alive'); - } - - /** - * 获取微信好友数量 - * - * @param string $ownerWechatId - * @return int - */ - protected function getFriendsCount(string $ownerWechatId): int - { - return WechatFriendShipModel::where( - [ - 'ownerWechatId' => $ownerWechatId, - //'companyId' => $this->getUserInfo('companyId'), - ] - ) - ->count(); - } - - /** - * 获取微信所属设备 - * - * @param string $wechatId - * @return string - */ - protected function getWhereOnDevice(string $wechatId): string - { - return (string)DeviceModel::alias('d') - ->where( - [ - 'l.wechatId' => $wechatId, - 'l.alive' => DeviceWechatLoginModel::ALIVE_WECHAT_ACTIVE, - 'l.companyId' => $this->getUserInfo('companyId') - ] - ) - ->join('device_wechat_login l', 'd.id = l.deviceId AND l.companyId = '. $this->getUserInfo('companyId')) - ->order('l.id desc') - ->value('d.memo'); - } - /** * 主操盘手获取项目下所有设备的id * @@ -172,22 +86,6 @@ class GetWechatsOnDevicesV1Controller extends BaseController ->column('wechatId'); } - /** - * TODO 获取设备最新活跃时间 - * - * @param string $wechatId - * @return string - */ - protected function getLatestActiveTime(string $wechatId): string - { - $wechatAccountId = Db::table('s2_wechat_account')->where(['wechatId' => $wechatId])->value('id'); - if (empty($wechatAccountId)){ - return '-'; - } - $time = Db::table('s2_wechat_message')->where('wechatAccountId',$wechatAccountId)->order('id DESC')->value('wechatTime'); - return !empty($time) ? date('Y-m-d H:i:s', $time) : '-'; - } - /** * 构建查询条件 * @@ -256,15 +154,26 @@ class GetWechatsOnDevicesV1Controller extends BaseController protected function makeResultedSet(\think\Paginator $result): array { $resultSets = []; + $items = $result->items(); - foreach ($result->items() as $item) { + if (empty($items)) { + return $resultSets; + } + + $wechatIds = array_values(array_unique(array_map(function ($item) { + return $item->wechatId ?? ($item['wechatId'] ?? ''); + }, $items))); + + $metrics = $this->collectWechatMetrics($wechatIds); + + foreach ($items as $item) { $sections = $item->toArray() + [ - 'times' => $this->getCanAddFriendCount($item->wechatId), - 'addedCount' => $this->getTodayNewFriendCount($item->wechatId), - 'wechatStatus' => $this->getWechatAddFriendStatus($item->wechatId), - 'totalFriend' => $this->getFriendsCount($item->wechatId), - 'deviceMemo' => $this->getWhereOnDevice($item->wechatId), - 'activeTime' => $this->getLatestActiveTime($item->wechatId), + 'times' => $metrics['addLimit'][$item->wechatId] ?? 0, + 'addedCount' => $metrics['todayAdded'][$item->wechatId] ?? 0, + 'wechatStatus' => $metrics['wechatStatus'][$item->wechatId] ?? 0, + 'totalFriend' => $metrics['totalFriend'][$item->wechatId] ?? 0, + 'deviceMemo' => $metrics['deviceMemo'][$item->wechatId] ?? '', + 'activeTime' => $metrics['activeTime'][$item->wechatId] ?? '-', ]; array_push($resultSets, $sections); @@ -273,6 +182,109 @@ class GetWechatsOnDevicesV1Controller extends BaseController return $resultSets; } + /** + * 批量收集微信账号的统计信息 + * @param array $wechatIds + * @return array + */ + protected function collectWechatMetrics(array $wechatIds): array + { + $metrics = [ + 'addLimit' => [], + 'todayAdded' => [], + 'totalFriend' => [], + 'wechatStatus' => [], + 'deviceMemo' => [], + 'activeTime' => [], + ]; + + if (empty($wechatIds)) { + return $metrics; + } + + $companyId = $this->getUserInfo('companyId'); + + // 可添加好友额度 + $weightRows = WechatCustomerModel::where('companyId', $companyId) + ->whereIn('wechatId', $wechatIds) + ->column('weight', 'wechatId'); + foreach ($weightRows as $wechatId => $weight) { + $decoded = json_decode($weight, true); + $metrics['addLimit'][$wechatId] = $decoded['addLimit'] ?? 0; + } + + // 今日新增好友 + $start = strtotime(date('Y-m-d 00:00:00')); + $end = strtotime(date('Y-m-d 23:59:59')); + $todayRows = WechatFriendShipModel::whereIn('ownerWechatId', $wechatIds) + ->whereBetween('createTime', [$start, $end]) + ->field('ownerWechatId, COUNT(*) as total') + ->group('ownerWechatId') + ->select(); + foreach ($todayRows as $row) { + $wechatId = is_array($row) ? ($row['ownerWechatId'] ?? '') : ($row->ownerWechatId ?? ''); + if ($wechatId) { + $metrics['todayAdded'][$wechatId] = (int)(is_array($row) ? ($row['total'] ?? 0) : ($row->total ?? 0)); + } + } + + // 总好友 + $friendRows = WechatFriendShipModel::whereIn('ownerWechatId', $wechatIds) + ->field('ownerWechatId, COUNT(*) as total') + ->group('ownerWechatId') + ->select(); + foreach ($friendRows as $row) { + $wechatId = is_array($row) ? ($row['ownerWechatId'] ?? '') : ($row->ownerWechatId ?? ''); + if ($wechatId) { + $metrics['totalFriend'][$wechatId] = (int)(is_array($row) ? ($row['total'] ?? 0) : ($row->total ?? 0)); + } + } + + // 设备状态与备注 + $loginRows = Db::name('device_wechat_login') + ->alias('l') + ->leftJoin('device d', 'd.id = l.deviceId') + ->field('l.wechatId,l.alive,d.memo') + ->where('l.companyId', $companyId) + ->whereIn('l.wechatId', $wechatIds) + ->order('l.id', 'desc') + ->select(); + foreach ($loginRows as $row) { + $wechatId = is_array($row) ? ($row['wechatId'] ?? '') : ($row->wechatId ?? ''); + if (empty($wechatId) || isset($metrics['wechatStatus'][$wechatId])) { + continue; + } + $metrics['wechatStatus'][$wechatId] = (int)(is_array($row) ? ($row['alive'] ?? 0) : ($row->alive ?? 0)); + $metrics['deviceMemo'][$wechatId] = is_array($row) ? ($row['memo'] ?? '') : ($row->memo ?? ''); + } + + // 活跃时间 + $accountMap = Db::table('s2_wechat_account') + ->whereIn('wechatId', $wechatIds) + ->column('id', 'wechatId'); + if (!empty($accountMap)) { + $accountRows = Db::table('s2_wechat_message') + ->whereIn('wechatAccountId', array_values($accountMap)) + ->field('wechatAccountId, MAX(wechatTime) as lastTime') + ->group('wechatAccountId') + ->select(); + $accountLastTime = []; + foreach ($accountRows as $row) { + $accountId = is_array($row) ? ($row['wechatAccountId'] ?? 0) : ($row->wechatAccountId ?? 0); + if ($accountId) { + $accountLastTime[$accountId] = (int)(is_array($row) ? ($row['lastTime'] ?? 0) : ($row->lastTime ?? 0)); + } + } + foreach ($accountMap as $wechatId => $accountId) { + if (isset($accountLastTime[$accountId]) && $accountLastTime[$accountId] > 0) { + $metrics['activeTime'][$wechatId] = date('Y-m-d H:i:s', $accountLastTime[$accountId]); + } + } + } + + return $metrics; + } + /** * 获取在线微信账号列表 *