From c09864ee89bd7c4dc93a00b889e77468f811adba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B3=E6=B8=85=E7=88=BD?= Date: Sat, 10 May 2025 10:17:58 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E7=A7=81=E5=9F=9F=E6=93=8D=E7=9B=98?= =?UTF-8?q?=E6=89=8B=20-=20=E9=87=8D=E5=86=99=E5=BE=AE=E4=BF=A1=E5=8F=B7?= =?UTF-8?q?=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/model/CompanyAccount.php | 131 --------- .../common/model/DeviceWechatLogin.php | 9 +- Server/application/common/model/User.php | 4 +- .../common/model/WechatAccount.php | 1 - .../application/common/model/WechatFriend.php | 4 + Server/application/cunkebao/config/route.php | 4 +- ...ler.php => GetAddResultedV1Controller.php} | 2 +- .../device/GetDeviceListV1Controller.php | 30 +- .../GetWechatsOnDevicesV1Controller.php | 263 ++++++++++++++++++ .../cunkebao/model/WechatAccount.php | 62 +---- 10 files changed, 306 insertions(+), 204 deletions(-) delete mode 100644 Server/application/common/model/CompanyAccount.php rename Server/application/cunkebao/controller/device/{GetAddResultedDevicesController.php => GetAddResultedV1Controller.php} (98%) create mode 100644 Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php diff --git a/Server/application/common/model/CompanyAccount.php b/Server/application/common/model/CompanyAccount.php deleted file mode 100644 index 12964bb7..00000000 --- a/Server/application/common/model/CompanyAccount.php +++ /dev/null @@ -1,131 +0,0 @@ - 'integer', - 'tenantId' => 'integer', - 'accountType' => 'integer', - 'companyId' => 'integer', - 'useGoogleSecretKey' => 'boolean', - 'hasVerifyGoogleSecret' => 'boolean', - 'lastLoginTime' => 'integer', - 'createTime' => 'integer', - 'updateTime' => 'integer' - ]; - - /** - * 获取公司账户信息 - * @param string $userName 用户名 - * @param string $password 密码(MD5加密后的) - * @return array|null - */ - public static function getAccount($userName, $password) - { - // 查询账户 - $account = self::where('userName', $userName) - ->find(); - - if (!$account) { - return null; - } - - // 验证密码 - if ($account->passwordMd5 !== $password) { - return null; - } - - // 更新登录信息 - $account->lastLoginIp = request()->ip(); - $account->lastLoginTime = time(); - $account->save(); - - return [ - 'id' => $account->id, - 'tenantId' => $account->tenantId, - 'userName' => $account->userName, - 'realName' => $account->realName, - 'nickname' => $account->nickname, - 'avatar' => $account->avatar, - 'accountType' => $account->accountType, - 'companyId' => $account->companyId, - 'lastLoginIp' => $account->lastLoginIp, - 'lastLoginTime' => $account->lastLoginTime - ]; - } - - /** - * 通过租户ID获取账户信息 - * @param int $companyId 租户ID - * @return array|null - */ - public static function getAccountByCompanyId($companyId) - { - // 查询账户 - $account = self::where('companyId', $companyId)->find(); - - if (!$account) { - return null; - } - - return [ - 'id' => $account->id, - 'tenantId' => $account->tenantId, - 'userName' => $account->userName, - 'realName' => $account->realName, - 'nickname' => $account->nickname, - 'avatar' => $account->avatar, - 'accountType' => $account->accountType, - 'companyId' => $account->companyId, - 'lastLoginIp' => $account->lastLoginIp, - 'lastLoginTime' => $account->lastLoginTime - ]; - } - -} \ No newline at end of file diff --git a/Server/application/common/model/DeviceWechatLogin.php b/Server/application/common/model/DeviceWechatLogin.php index 290ed32a..5b18762a 100644 --- a/Server/application/common/model/DeviceWechatLogin.php +++ b/Server/application/common/model/DeviceWechatLogin.php @@ -9,6 +9,9 @@ use think\Model; */ class DeviceWechatLogin extends Model { + const ALIVE_WECHAT_ACTIVE = 1; // 微信在线 + const ALIVE_WECHAT_DIED = 0; // 微信离线 + // 登录日志最新登录 alive = 1,旧数据全部设置0 protected $name = 'device_wechat_login'; @@ -25,6 +28,10 @@ class DeviceWechatLogin extends Model */ public static function getDevicesLatestLogin(array $deviceIds): array { - return self::fieldRaw('max(id) as lastedId,deviceId')->whereIn('deviceId', $deviceIds)->group('deviceId')->select()->toArray(); + return static::fieldRaw('max(id) as lastedId,deviceId') + ->whereIn('deviceId', $deviceIds) + ->group('deviceId') + ->select() + ->toArray(); } } \ No newline at end of file diff --git a/Server/application/common/model/User.php b/Server/application/common/model/User.php index f691a82c..9117d783 100644 --- a/Server/application/common/model/User.php +++ b/Server/application/common/model/User.php @@ -9,9 +9,9 @@ class User extends Model { use SoftDelete; - const ADMIN_STP = 1; + const ADMIN_STP = 1; // 主操盘手账号 const ADMIN_OTP = 0; - const NOT_USER = -1; + const NOT_USER = -1; // 非登录用户用于任务操作的(S2系统专属) const MASTER_USER = 1; // 操盘手 const CUSTOMER_USER = 2; // 门店接待 const STATUS_STOP = 0; // 禁用状态 diff --git a/Server/application/common/model/WechatAccount.php b/Server/application/common/model/WechatAccount.php index 5deae91f..4c7da606 100644 --- a/Server/application/common/model/WechatAccount.php +++ b/Server/application/common/model/WechatAccount.php @@ -16,5 +16,4 @@ class WechatAccount extends Model protected $autoWriteTimestamp = true; protected $createTime = 'createTime'; protected $updateTime = 'updateTime'; - protected $defaultSoftDelete = 0; } \ No newline at end of file diff --git a/Server/application/common/model/WechatFriend.php b/Server/application/common/model/WechatFriend.php index c2c5be77..5c121c82 100644 --- a/Server/application/common/model/WechatFriend.php +++ b/Server/application/common/model/WechatFriend.php @@ -3,12 +3,15 @@ namespace app\common\model; use think\Model; +use think\model\concern\SoftDelete; /** * 微信好友模型类 */ class WechatFriend extends Model { + use SoftDelete; + // 设置表名 protected $name = 'wechat_friend'; @@ -16,5 +19,6 @@ class WechatFriend extends Model protected $autoWriteTimestamp = true; protected $createTime = 'createTime'; protected $updateTime = 'updateTime'; + protected $deleteTime = 'deleteTime'; protected $defaultSoftDelete = 0; } \ No newline at end of file diff --git a/Server/application/cunkebao/config/route.php b/Server/application/cunkebao/config/route.php index 0ce2a9dc..415e811c 100644 --- a/Server/application/cunkebao/config/route.php +++ b/Server/application/cunkebao/config/route.php @@ -10,7 +10,7 @@ Route::group('v1/', function () { // 设备管理相关 Route::group('devices', function () { - Route::get('add-results', 'app\cunkebao\controller\device\GetAddResultedDevicesController@index'); // 更新设备任务配置 + Route::get('add-results', 'app\cunkebao\controller\device\GetAddResultedV1Controller@index'); // 更新设备任务配置 Route::get(':id/related-accounts', 'app\cunkebao\controller\device\GetRelatedAccountsV1Controller@index'); // 设备关联微信账号路由 Route::get(':id/handle-logs', 'app\cunkebao\controller\device\GetDeviceHandleLogsV1Controller@index'); // 获取设备操作记录 Route::get('', 'app\cunkebao\controller\device\GetDeviceListV1Controller@index'); // 获取设备列表 @@ -23,10 +23,10 @@ Route::group('v1/', function () { // 设备微信相关 Route::group('device/wechats', function () { + Route::get('', 'app\cunkebao\controller\wechat\GetWechatsOnDevicesV1Controller@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::get('', 'app\cunkebao\controller\DeviceWechat@index'); // 获取在线微信账号列表 Route::get(':id', 'app\cunkebao\controller\DeviceWechat@detail'); // 获取微信号详情 Route::put('refresh', 'app\cunkebao\controller\DeviceWechat@refresh'); // 刷新设备微信状态 Route::post('transfer-friends', 'app\cunkebao\controller\DeviceWechat@transferFriends'); // 微信好友转移 diff --git a/Server/application/cunkebao/controller/device/GetAddResultedDevicesController.php b/Server/application/cunkebao/controller/device/GetAddResultedV1Controller.php similarity index 98% rename from Server/application/cunkebao/controller/device/GetAddResultedDevicesController.php rename to Server/application/cunkebao/controller/device/GetAddResultedV1Controller.php index 86a166a0..e9cb20fa 100644 --- a/Server/application/cunkebao/controller/device/GetAddResultedDevicesController.php +++ b/Server/application/cunkebao/controller/device/GetAddResultedV1Controller.php @@ -12,7 +12,7 @@ use think\Db; /** * 设备控制器 */ -class GetAddResultedDevicesController extends BaseController +class GetAddResultedV1Controller extends BaseController { /** * 通过账号id 获取项目id。 diff --git a/Server/application/cunkebao/controller/device/GetDeviceListV1Controller.php b/Server/application/cunkebao/controller/device/GetDeviceListV1Controller.php index aa7ef9a9..de211114 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; +use app\common\model\WechatFriend as WechatFriendModel; use app\cunkebao\controller\BaseController; use library\ResponseHelper; @@ -22,8 +22,6 @@ class GetDeviceListV1Controller extends BaseController */ protected function makeWhere(array $params = []): array { - $where = []; - // 关键词搜索(同时搜索IMEI和备注) if (!empty($keyword = $this->request->param('keyword'))) { $where[] = ['exp', "d.imei LIKE '%{$keyword}%' OR d.memo LIKE '%{$keyword}%'"]; @@ -47,8 +45,10 @@ class GetDeviceListV1Controller extends BaseController protected function makeDeviceIdsWhere(): array { $deviceIds = DeviceUserModel::where( - $this->getUserInfo('id'), - $this->getUserInfo('companyId') + [ + 'userId' => $this->getUserInfo('id'), + 'companyId' => $this->getUserInfo('companyId') + ] ) ->column('deviceId'); @@ -56,7 +56,7 @@ class GetDeviceListV1Controller extends BaseController throw new \Exception('请联系管理员绑定设备', 403); } - $where['d.id'] = ['in', $deviceIds]; + $where['d.id'] = array('in', $deviceIds); return $where; } @@ -65,11 +65,9 @@ class GetDeviceListV1Controller extends BaseController * 获取设备列表 * * @param array $where 查询条件 - * @param int $page 页码 - * @param int $limit 每页数量 * @return \think\Paginator 分页对象 */ - protected function getDeviceList(array $where, int $page = 1, int $limit = 10): \think\Paginator + protected function getDeviceList(array $where): \think\Paginator { $query = DeviceModel::alias('d') ->field([ @@ -101,16 +99,16 @@ class GetDeviceListV1Controller extends BaseController */ protected function countFriend(\think\Paginator $list): array { - $result = []; + $resultSets = []; foreach ($list->items() as $item) { - $section = $item->toArray(); + $sections = $item->toArray(); if ($item->wechatId) { - $section['totalFriend'] = WechatFriend::where(['ownerWechatId' => $section['wechatId']])->count(); + $sections['totalFriend'] = WechatFriendModel::where(['ownerWechatId' => $item->wechatId])->count(); } - array_push($result, $section); + array_push($result, $sections); } return $result; @@ -126,8 +124,10 @@ class GetDeviceListV1Controller extends BaseController if ($this->getUserInfo('isAdmin') == UserModel::ADMIN_STP) { $where = $this->makeWhere(); $result = $this->getDeviceList($where); - } else { - $where = $this->makeWhere($this->makeDeviceIdsWhere()); + } + + else { + $where = $this->makeWhere( $this->makeDeviceIdsWhere() ); $result = $this->getDeviceList($where); } diff --git a/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php b/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php new file mode 100644 index 00000000..81cce9c1 --- /dev/null +++ b/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php @@ -0,0 +1,263 @@ +count(); + } + + /** + * 获取微信所属设备 + * + * @param string $wechatId + * @return string + */ + protected function getWhereOnDevice(string $wechatId): string + { + return DeviceModel::alias('d') + ->where( + [ + 'l.wechatId' => $wechatId, + 'l.alive' => DeviceWechatLoginModel::ALIVE_WECHAT_ACTIVE + ] + ) + ->join('device_wechat_login l', 'd.id = l.deviceId') + ->value('d.imei'); + } + + /** + * 主操盘手获取项目下所有设备的id + * + * @return array + * @throws \Exception + */ + protected function getCompanyDevicesId(): array + { + return DevicesModel::where( + [ + 'companyId' => $this->getUserInfo('companyId') + ] + ) + ->column('id'); + } + + /** + * 非主操盘手获取分配的设备 + * + * @return array + */ + protected function getUserDevicesId(): array + { + return DeviceUserModel::where( + [ + 'userId' => $this->getUserInfo('id'), + 'companyId' => $this->getUserInfo('companyId') + ] + ) + ->column('deviceId'); + } + + /** + * 根据不同角色,显示的设备数量不同 + * + * @return array + * @throws \Exception + */ + protected function getDevicesId(): array + { + return ($this->getUserInfo('isAdmin') == UserModel::ADMIN_STP) + ? $this->getCompanyDevicesId() // 主操盘手获取所有的设备 + : $this->getUserDevicesId(); // 非主操盘手获取分配的设备 + } + + /** + * 获取有登录设备的微信id + * + * @return array + */ + protected function getWechatIdsOnDevices(): array + { + // 关联设备id查询,过滤掉已删除的设备 + if (empty($deviceIds = $this->getDevicesId())) { + throw new \Exception('暂无设备数据', 200); + } + + return DeviceWechatLoginModel::where( + [ + 'companyId' => $this->getUserInfo('companyId'), + 'alive' => DeviceWechatLoginModel::ALIVE_WECHAT_ACTIVE, + ] + ) + ->where('deviceId', 'in', $deviceIds) + ->column('wechatId'); + } + + /** + * 获取设备最新活跃时间 + * + * @param string $wechatId + * @return string + */ + protected function getLatestActiveTime(string $wechatId): string + { + return date('Y-m-d H:i:s', strtotime('-1 day')); + } + + /** + * 构建查询条件 + * + * @param array $params + * @return array + */ + protected function makeWhere(array $params = []): array + { + if (empty($wechatIds = $this->getWechatIdsOnDevices())) { + throw new \Exception('设备尚未有登录微信', 200); + } + + // 关键词搜索(同时搜索微信号和昵称) + if (!empty($keyword = $this->request->param('keyword'))) { + $where[] = ['exp', "w.alias LIKE '%{$keyword}%' OR w.nickname LIKE '%{$keyword}%'"]; + } + + $where['w.wechatId'] = array('in', implode(',', $wechatIds)); + + return array_merge($params, $where); + } + + /** + * 获取在线微信账号列表 + * + * @param array $where + * @return \think\Paginator 分页对象 + */ + protected function getOnlineWechatList(array $where): \think\Paginator + { + $query = WechatAccountModel::alias('w') + ->field([ + 'w.id', 'w.wechatId', 'w.nickname', 'w.avatar', 'w.s2_wechatAccountId' + ]) + ->order('w.id desc'); + + foreach ($where as $key => $value) { + if (is_numeric($key) && is_array($value) && isset($value[0]) && $value[0] === 'exp') { + $query->whereExp('', $value[1]); + continue; + } + + if (is_array($value)) { + $query->where($key, ...$value); + continue; + } + + $query->where($key, $value); + } + + return $query->paginate($this->request->param('limit/d', 10), false, ['page' => $this->request->param('page/d', 1)]); + } + + /** + * 构建返回数据 + * + * @param \think\Paginator $result + * @return array + */ + protected function makeResultedSet(\think\Paginator $result): array + { + $resultSets = []; + + foreach ($result->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), + ]; + + array_push($resultSets, $sections); + } + + return $resultSets; + } + + /** + * 获取在线微信账号列表 + * @return \think\response\Json + */ + public function index() + { + try { + $result = $this->getOnlineWechatList( + $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/model/WechatAccount.php b/Server/application/cunkebao/model/WechatAccount.php index df58cc7e..b8a68ca2 100644 --- a/Server/application/cunkebao/model/WechatAccount.php +++ b/Server/application/cunkebao/model/WechatAccount.php @@ -1,4 +1,5 @@ 1, 'wechatAlive' => 1, - 'isDeleted' => 0 + 'isDeleted' => 0 ]; - + // 合并额外条件 if (!empty($where)) { $condition = array_merge($condition, $where); } - + return self::where($condition)->count(); } - + /** * 获取有登录微信的设备数量 - * + * * @param array $where 额外的查询条件 * @return int 设备数量 */ @@ -43,55 +44,14 @@ class WechatAccount extends Model { $condition = [ 'deviceAlive' => 1, - 'isDeleted' => 0 + 'isDeleted' => 0 ]; - + // 合并额外条件 if (!empty($where)) { $condition = array_merge($condition, $where); } - + return self::where($condition)->count(); } - - /** - * 获取在线微信账号列表 - * - * @param array $where 额外的查询条件 - * @param string $order 排序方式 - * @param int $page 页码 - * @param int $limit 每页数量 - * @return \think\Paginator 分页对象 - */ - public static function getOnlineWechatList($where = [], $order = 'id desc', $page = 1, $limit = 10) - { - $condition = [ - 'isDeleted' => 0 - ]; - - // 合并额外条件 - if (!empty($where)) { - $condition = array_merge($condition, $where); - } - - return self::where($condition) - ->field([ - 'id', - 'wechatId', - 'accountNickname', - 'nickname', - 'accountUserName', - 'avatar', - 'wechatAlive', - 'deviceAlive', - 'totalFriend', - 'maleFriend', - 'femaleFriend', - 'imei', - 'deviceMemo', - 'yesterdayMsgCount' - ]) - ->order($order) - ->paginate($limit, false, ['page' => $page]); - } } \ No newline at end of file From 556d0ae977f49b4e442879978204a621ae6d7bd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B3=E6=B8=85=E7=88=BD?= Date: Sat, 10 May 2025 10:22:55 +0800 Subject: [PATCH 2/9] =?UTF-8?q?=E7=A7=81=E5=9F=9F=E6=93=8D=E7=9B=98?= =?UTF-8?q?=E6=89=8B=20-=20=E4=BF=AE=E5=A4=8D=E8=AE=BE=E5=A4=87=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=95=B0=E6=8D=AE=E6=8F=92=E5=85=A5=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cunkebao/controller/device/GetDeviceListV1Controller.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Server/application/cunkebao/controller/device/GetDeviceListV1Controller.php b/Server/application/cunkebao/controller/device/GetDeviceListV1Controller.php index de211114..787ba998 100644 --- a/Server/application/cunkebao/controller/device/GetDeviceListV1Controller.php +++ b/Server/application/cunkebao/controller/device/GetDeviceListV1Controller.php @@ -108,10 +108,10 @@ class GetDeviceListV1Controller extends BaseController $sections['totalFriend'] = WechatFriendModel::where(['ownerWechatId' => $item->wechatId])->count(); } - array_push($result, $sections); + array_push($resultSets, $sections); } - return $result; + return $resultSets; } /** From 24fc116d9b136b89eafafac50b113cc1082cc0f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B3=E6=B8=85=E7=88=BD?= Date: Sat, 10 May 2025 11:04:00 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E7=A7=81=E5=9F=9F=E6=93=8D=E7=9B=98?= =?UTF-8?q?=E6=89=8B=20-=20=E8=B0=83=E6=95=B4=E5=BE=AE=E4=BF=A1=E5=8F=B7?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E8=BF=94=E5=9B=9E=E5=AD=97=E6=AE=B5=EF=BC=8C?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=B7=BB=E5=8A=A0=E5=A5=BD=E5=8F=8B=E8=BF=9B?= =?UTF-8?q?=E5=BA=A6=E8=AE=A1=E7=AE=97=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cunkebao/app/wechat-accounts/page.tsx | 39 +++++++++++++++++-- .../GetWechatsOnDevicesV1Controller.php | 21 +++++----- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/Cunkebao/app/wechat-accounts/page.tsx b/Cunkebao/app/wechat-accounts/page.tsx index c831b383..e814b928 100644 --- a/Cunkebao/app/wechat-accounts/page.tsx +++ b/Cunkebao/app/wechat-accounts/page.tsx @@ -20,9 +20,23 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from " import { toast } from "@/components/ui/use-toast" import { Progress } from "@/components/ui/progress" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip" -import { fetchWechatAccountList, refreshWechatAccounts, transferWechatFriends, transformWechatAccount } from "@/api/wechat-accounts" +import { fetchWechatAccountList, refreshWechatAccounts, transferWechatFriends } from "@/api/wechat-accounts" import { WechatAccount } from "@/types/wechat-account" +// 定义接口以匹配新的数据结构 +interface WechatAccountResponse { + id: number + wechatId: string + nickname: string + avatar: string + times: number + addedCount: number + wechatStatus: number + totalFriend: number + deviceMemo: string + activeTime: string +} + export default function WechatAccountsPage() { const router = useRouter() const [accounts, setAccounts] = useState([]) @@ -49,7 +63,23 @@ export default function WechatAccountsPage() { if (response && response.code === 200 && response.data) { // 转换数据格式 - const wechatAccounts = response.data.list.map(transformWechatAccount); + const wechatAccounts = response.data.list.map((item: any) => { + const account: WechatAccount = { + id: item.id.toString(), + wechatId: item.wechatId, + nickname: item.nickname, + avatar: item.avatar, + remainingAdds: item.times - item.addedCount, + todayAdded: item.addedCount, + status: item.wechatStatus === 1 ? "normal" as const : "abnormal" as const, + friendCount: item.totalFriend, + deviceName: item.deviceMemo, + lastActive: item.activeTime, + maxDailyAdds: item.times, + deviceId: item.id.toString(), + }; + return account; + }); setAccounts(wechatAccounts); setTotalAccounts(response.data.total); } else { @@ -279,7 +309,10 @@ export default function WechatAccountsPage() { {account.todayAdded}/{account.maxDailyAdds} - +
所属设备:{account.deviceName || '未知设备'}
diff --git a/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php b/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php index 81cce9c1..3554d3aa 100644 --- a/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php +++ b/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php @@ -18,16 +18,14 @@ use library\ResponseHelper; class GetWechatsOnDevicesV1Controller extends BaseController { /** - * TODO 计算今日可添加好友数量 + * 计算今日可添加好友数量 * * @param string $wechatId * @return int */ protected function getCanAddFriendCount(string $wechatId): int { - $canAddFriendCount = 20; // 最多限制 20 次 - - return $canAddFriendCount < 0 ? 0 : $canAddFriendCount; + return 20; // 最多限制 20 次 } /** @@ -71,7 +69,7 @@ class GetWechatsOnDevicesV1Controller extends BaseController */ protected function getWhereOnDevice(string $wechatId): string { - return DeviceModel::alias('d') + return (string)DeviceModel::alias('d') ->where( [ 'l.wechatId' => $wechatId, @@ -79,7 +77,7 @@ class GetWechatsOnDevicesV1Controller extends BaseController ] ) ->join('device_wechat_login l', 'd.id = l.deviceId') - ->value('d.imei'); + ->value('d.memo'); } /** @@ -150,7 +148,7 @@ class GetWechatsOnDevicesV1Controller extends BaseController } /** - * 获取设备最新活跃时间 + * TODO 获取设备最新活跃时间 * * @param string $wechatId * @return string @@ -191,9 +189,12 @@ class GetWechatsOnDevicesV1Controller extends BaseController protected function getOnlineWechatList(array $where): \think\Paginator { $query = WechatAccountModel::alias('w') - ->field([ - 'w.id', 'w.wechatId', 'w.nickname', 'w.avatar', 'w.s2_wechatAccountId' - ]) + ->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', + ] + ) ->order('w.id desc'); foreach ($where as $key => $value) { From 6d9d56008def595ff3bf504754282e15fd6de19a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B3=E6=B8=85=E7=88=BD?= Date: Sat, 10 May 2025 11:19:51 +0800 Subject: [PATCH 4/9] =?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=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E8=AE=A1=E7=AE=97=E4=BB=8A=E6=97=A5=E6=96=B0=E5=A2=9E=E5=A5=BD?= =?UTF-8?q?=E5=8F=8B=E6=95=B0=E9=87=8F=E8=A1=A5=E5=85=85=E4=B8=9A=E5=8A=A1?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wechat/GetWechatsOnDevicesV1Controller.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php b/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php index 3554d3aa..84e008fb 100644 --- a/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php +++ b/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php @@ -29,14 +29,21 @@ class GetWechatsOnDevicesV1Controller extends BaseController } /** - * TODO 计算今日新增好友数量 + * 计算今日新增好友数量 * - * @param string $wechatId + * @param string $ownerWechatId * @return int */ - protected function getTodayNewFriendCount(string $wechatId): int + protected function getTodayNewFriendCount(string $ownerWechatId): int { - return 0; + return WechatFriendModel::where( compact('ownerWechatId') ) + ->whereBetween('createTime', + [ + strtotime(date('Y-m-d 00:00:00')), + strtotime(date('Y-m-d 23:59:59')) + ] + ) + ->count('*'); } /** From 2bb3f3de5ddb0e0c7cae26e866403bb88f7d096c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B3=E6=B8=85=E7=88=BD?= Date: Sat, 10 May 2025 12:02:19 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E7=A7=81=E5=9F=9F=E6=93=8D=E7=9B=98?= =?UTF-8?q?=E6=89=8B=20-=20=E8=B0=83=E6=95=B4=E5=BE=AE=E4=BF=A1=E5=8F=B7?= =?UTF-8?q?=E8=AF=A6=E6=83=85=E9=A1=B5=E9=83=A8=E5=88=86=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=EF=BC=8C=E4=BD=BF=E7=94=A8=E8=B7=B3=E8=BD=AC?= =?UTF-8?q?=E6=97=B6=E4=BC=A0=E9=80=92=E7=9A=84=E5=88=97=E8=A1=A8=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E8=80=8C=E4=B8=8D=E6=98=AF=E6=8E=A5=E5=8F=A3=E6=95=B0?= =?UTF-8?q?=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cunkebao/app/wechat-accounts/[id]/page.tsx | 50 +++++- Cunkebao/app/wechat-accounts/page.tsx | 12 +- Server/application/cunkebao/config/route.php | 8 +- ...GetWechatOnDeviceSummarizeV1Controller.php | 152 ++++++++++++++++++ 4 files changed, 216 insertions(+), 6 deletions(-) create mode 100644 Server/application/cunkebao/controller/wechat/GetWechatOnDeviceSummarizeV1Controller.php diff --git a/Cunkebao/app/wechat-accounts/[id]/page.tsx b/Cunkebao/app/wechat-accounts/[id]/page.tsx index 672b0f87..576a38c2 100644 --- a/Cunkebao/app/wechat-accounts/[id]/page.tsx +++ b/Cunkebao/app/wechat-accounts/[id]/page.tsx @@ -134,6 +134,28 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri const friendsLoadingRef = useRef(null) const friendsContainerRef = useRef(null) + const [initialData, setInitialData] = useState<{ + avatar: string; + nickname: string; + status: "normal" | "abnormal"; + wechatId: string; + deviceName: string; + } | null>(null) + + useEffect(() => { + // 从 URL 参数中获取初始数据 + const searchParams = new URLSearchParams(window.location.search); + const dataParam = searchParams.get('data'); + if (dataParam) { + try { + const decodedData = JSON.parse(decodeURIComponent(dataParam)); + setInitialData(decodedData); + } catch (error) { + console.error('解析初始数据失败:', error); + } + } + }, []); + // 计算好友列表容器高度 const getFriendsContainerHeight = () => { // 最少显示一条记录的高度,最多显示十条记录的高度 @@ -411,6 +433,14 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri 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状态 @@ -425,6 +455,14 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri }) // 获取失败时使用模拟数据 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); @@ -438,6 +476,14 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri }) // 请求出错时使用模拟数据 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); @@ -447,7 +493,7 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri } fetchAccount() - }, [params.id]) + }, [params.id, initialData]) if (!account) { return
加载中...
@@ -534,7 +580,7 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri {account.nickname[0]} {account.isVerified && ( - + 已认证 )} diff --git a/Cunkebao/app/wechat-accounts/page.tsx b/Cunkebao/app/wechat-accounts/page.tsx index e814b928..d3a995f6 100644 --- a/Cunkebao/app/wechat-accounts/page.tsx +++ b/Cunkebao/app/wechat-accounts/page.tsx @@ -256,7 +256,17 @@ export default function WechatAccountsPage() { router.push(`/wechat-accounts/${account.id}`)} + onClick={() => { + // 将需要的数据编码为 URL 安全的字符串 + const accountData = encodeURIComponent(JSON.stringify({ + avatar: account.avatar, + nickname: account.nickname, + status: account.status, + wechatId: account.wechatId, + deviceName: account.deviceName, + })); + router.push(`/wechat-accounts/${account.id}?data=${accountData}`); + }} >
diff --git a/Server/application/cunkebao/config/route.php b/Server/application/cunkebao/config/route.php index 415e811c..cc4fb315 100644 --- a/Server/application/cunkebao/config/route.php +++ b/Server/application/cunkebao/config/route.php @@ -7,7 +7,6 @@ use think\facade\Route; // 定义RESTful风格的API路由 Route::group('v1/', function () { - // 设备管理相关 Route::group('devices', function () { Route::get('add-results', 'app\cunkebao\controller\device\GetAddResultedV1Controller@index'); // 更新设备任务配置 @@ -24,10 +23,13 @@ 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('friends', 'app\cunkebao\controller\DeviceWechat@getFriends'); // 获取微信好友列表 Route::get('count', 'app\cunkebao\controller\DeviceWechat@count'); // 获取在线微信账号数量 Route::get('device-count', 'app\cunkebao\controller\DeviceWechat@deviceCount'); // 获取有登录微信的设备数量 - Route::get(':id', 'app\cunkebao\controller\DeviceWechat@detail'); // 获取微信号详情 Route::put('refresh', 'app\cunkebao\controller\DeviceWechat@refresh'); // 刷新设备微信状态 Route::post('transfer-friends', 'app\cunkebao\controller\DeviceWechat@transferFriends'); // 微信好友转移 }); @@ -78,7 +80,7 @@ Route::group('v1/', function () { Route::group('chatroom', function () { Route::get('', 'app\cunkebao\controller\chatroom\GetChatroomListV1Controller@index'); // 获取群列表 Route::get('getMemberList', 'app\cunkebao\controller\chatroom\GetChatroomListV1Controller@getMemberList'); // 获取群详情 - + }); // 计划任务相关路由 diff --git a/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceSummarizeV1Controller.php b/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceSummarizeV1Controller.php new file mode 100644 index 00000000..e2a5d02c --- /dev/null +++ b/Server/application/cunkebao/controller/wechat/GetWechatOnDeviceSummarizeV1Controller.php @@ -0,0 +1,152 @@ +request->param('id/d')); + + + dd( + + $aa->toArray() + ); + + } + + + + + /** + * 获取微信号详情 + * + * @return \think\response\Json + */ + public function index() + { + try { + + + + $this->getWechatAccount(); + + + + + + + // 获取微信号基本信息 + $wechat = WechatAccountModel::where('id', $id) + ->where('isDeleted', 0) + ->find(); + + if (!$wechat) { + return json([ + 'code' => 404, + 'msg' => '微信号不存在' + ]); + } + + // 计算账号年龄(从创建时间到现在) + $accountAge = 0; + if ($wechat['createTime']) { + $createTime = strtotime($wechat['createTime']); + $now = time(); + $accountAge = floor(($now - $createTime) / (24 * 3600)); + } + + // 计算活跃程度(根据消息数) + $activityLevel = '低'; + if ($wechat['thirtyDayMsgCount'] > 1000) { + $activityLevel = '高'; + } elseif ($wechat['thirtyDayMsgCount'] > 500) { + $activityLevel = '中'; + } + + // 评估账号权重(示例算法) + $weight = 0; + // 基础权重 + $weight += 10; + // 好友数量权重 + $weight += min($wechat['totalFriend'] / 100, 20); + // 活跃度权重 + $weight += min($wechat['thirtyDayMsgCount'] / 100, 20); + // 账号年龄权重 + $weight += min($accountAge / 30, 10); + // 在线状态权重 + if ($wechat['wechatAlive']) { + $weight += 5; + } + + // 获取限制记录(示例数据,实际需要从数据库获取) + $restrictions = [ + [ + 'type' => '添加好友限制', + 'reason' => '频繁添加好友', + 'startTime' => date('Y-m-d H:i:s', strtotime('-1 day')), + 'endTime' => date('Y-m-d H:i:s', strtotime('+1 day')) + ] + ]; + + // 处理返回数据 + $data = [ + 'basicInfo' => [ + 'id' => $wechat['id'], + 'wechatId' => $wechat['wechatId'], + 'nickname' => $wechat['nickname'] ?: $wechat['accountNickname'], + 'avatar' => $wechat['avatar'], + 'status' => $wechat['wechatAlive'] ? '在线' : '离线', + 'deviceStatus' => $wechat['deviceAlive'] ? '在线' : '离线', + 'deviceInfo' => $wechat['imei'] . ($wechat['deviceMemo'] ? " ({$wechat['deviceMemo']})" : ''), + 'gender' => $wechat['gender'], + 'region' => $wechat['region'], + 'signature' => $wechat['signature'] + ], + 'statistics' => [ + 'totalFriend' => $wechat['totalFriend'], + 'maleFriend' => $wechat['maleFriend'], + 'femaleFriend' => $wechat['femaleFriend'], + 'canAddFriendCount' => 30 - (isset($wechat['yesterdayMsgCount']) ? intval($wechat['yesterdayMsgCount']) : 0), + 'yesterdayMsgCount' => $wechat['yesterdayMsgCount'], + 'sevenDayMsgCount' => $wechat['sevenDayMsgCount'], + 'thirtyDayMsgCount' => $wechat['thirtyDayMsgCount'] + ], + 'accountInfo' => [ + 'age' => $accountAge, + 'activityLevel' => $activityLevel, + 'weight' => round($weight, 2), + 'createTime' => $wechat['createTime'], + 'lastUpdateTime' => $wechat['updateTime'] + ], + 'restrictions' => $restrictions, + ]; + + return json([ + 'code' => 200, + 'msg' => '获取成功', + 'data' => $data + ]); + } catch (\Exception $e) { + return json([ + 'code' => 500, + 'msg' => '获取失败:' . $e->getMessage() + ]); + } + } +} \ No newline at end of file From dd6173648806139f7bbecb4d96187544e40ba848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B3=E6=B8=85=E7=88=BD?= Date: Sat, 10 May 2025 14:20:58 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E7=A7=81=E5=9F=9F=E6=93=8D=E7=9B=98?= =?UTF-8?q?=E6=89=8B=20-=20=E4=BF=AE=E5=A4=8D=E5=BE=AE=E4=BF=A1=E5=8F=B7?= =?UTF-8?q?=E8=AF=A6=E6=83=85=E8=BF=9B=E5=85=A5=E8=AE=BE=E5=A4=87=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E4=BC=A0=E5=8F=82=E9=94=99=E8=AF=AF=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cunkebao/app/wechat-accounts/[id]/page.tsx | 15 +++++++++++++-- Cunkebao/app/wechat-accounts/page.tsx | 3 ++- .../wechat/GetWechatsOnDevicesV1Controller.php | 2 ++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Cunkebao/app/wechat-accounts/[id]/page.tsx b/Cunkebao/app/wechat-accounts/[id]/page.tsx index 576a38c2..8df347b9 100644 --- a/Cunkebao/app/wechat-accounts/[id]/page.tsx +++ b/Cunkebao/app/wechat-accounts/[id]/page.tsx @@ -140,6 +140,7 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri status: "normal" | "abnormal"; wechatId: string; deviceName: string; + deviceId?: string | number; } | null>(null) useEffect(() => { @@ -594,9 +595,19 @@ export default function WechatAccountDetailPage({ params }: { params: { id: stri

微信号:{account.wechatId}

-