123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 |
- <?php
- // +----------------------------------------------------------------------
- // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
- // +----------------------------------------------------------------------
- // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
- // +----------------------------------------------------------------------
- // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
- // +----------------------------------------------------------------------
- // | Author: CRMEB Team <admin@crmeb.com>
- // +----------------------------------------------------------------------
- namespace app\services\work;
- use app\dao\work\WorkGroupChatDao;
- use app\jobs\work\WorkClientJob;
- use app\jobs\work\WorkGroupChatJob;
- use app\services\BaseServices;
- use crmeb\services\wechat\config\WorkConfig;
- use crmeb\services\wechat\Work;
- use crmeb\traits\ServicesTrait;
- use think\db\exception\DataNotFoundException;
- use think\db\exception\DbException;
- use think\db\exception\ModelNotFoundException;
- use think\exception\ValidateException;
- /**
- * Class WorkGroupChatServices
- * @package app\services\work
- * @mixin WorkGroupChatDao
- */
- class WorkGroupChatServices extends BaseServices
- {
- use ServicesTrait;
- /**
- * WorkGroupChatServices constructor.
- * @param WorkGroupChatDao $dao
- */
- public function __construct(WorkGroupChatDao $dao)
- {
- $this->dao = $dao;
- }
- /**
- * 获取客户群群发列表
- * @param array $where
- * @param array $with
- * @return array
- * @throws DataNotFoundException
- * @throws DbException
- * @throws ModelNotFoundException
- */
- public function groupChatList(array $where, array $with = [])
- {
- [$page, $limit] = $this->getPageValue();
- $list = $this->dao->groupChat($where)->with($with)->page($page, $limit)->select()->toArray();
- $count = $this->dao->groupChat($where)->count();
- return compact('list', 'count');
- }
- /**
- * 群发详情列表
- * @param array $chatIds
- * @return array
- * @throws DataNotFoundException
- * @throws DbException
- * @throws ModelNotFoundException
- */
- public function getOwnerChatList(array $chatIds, $status = null)
- {
- return $this->groupChatList(['chat_id' => $chatIds, 'status' => $status], [
- 'sendResult' => function ($query) {
- $query->field(['chat_id', 'status']);
- }, 'chatMember' => function ($query) {
- $query->field(['count(*) as sun', 'group_id']);
- }
- ]);
- }
- /**
- * 同步企业微信客户群
- * @param string|null $nextCursor
- * @return bool
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/10/10
- */
- public function authGroupChat(string $nextCursor = null)
- {
- /** @var WorkConfig $confg */
- $config = app()->make(WorkConfig::class);
- $corpId = $config->get('corpId');
- if (!$corpId) {
- throw new ValidateException('请先配置企业微信ID');
- }
- $res = Work::getGroupChats([], 100, $nextCursor);
- if (0 !== ($res['errcode'] ?? 0)) {
- throw new ValidateException($res['errmsg']);
- }
- $groupChatList = $res['group_chat_list'] ?? [];
- if ($groupChatList) {
- $groupChat = [];
- foreach ($groupChatList as $item) {
- $item['corp_id'] = $corpId;
- if (($id = $this->dao->value(['chat_id' => $item['chat_id'], 'corp_id' => $corpId], 'id'))) {
- $this->dao->update($id, $item);
- } else {
- $item['create_time'] = time();
- $groupChat[] = $item;
- }
- }
- if ($groupChat) {
- $this->dao->saveAll($groupChat);
- }
- foreach ($groupChatList as $item) {
- WorkGroupChatJob::dispatchDo('authChat', [$corpId, $item['chat_id']]);
- }
- //如果有下一页继续执行
- if (!empty($res['next_cursor'])) {
- WorkGroupChatJob::dispatchDo('authGroupChat', [$res['next_cursor']]);
- }
- }
- return true;
- }
- /**
- * 保存群详情
- * @param string $corpId
- * @param string $chatId
- * @return bool
- * @throws DataNotFoundException
- * @throws DbException
- * @throws ModelNotFoundException
- */
- public function saveWorkGroupChat(string $corpId, string $chatId)
- {
- $response = Work::getGroupChat($chatId);
- if (0 !== $response['errcode']) {
- throw new ValidateException($response['errmsg']);
- }
- $groupInfo = $response['group_chat'] ?? [];
- $groupInfo['admin_list'] = json_encode(array_column($groupInfo['admin_list'], 'userid'));
- $memberList = $groupInfo['member_list'] ?? [];
- unset($groupInfo['member_list']);
- $group = $this->dao->get(['corp_id' => $corpId, 'chat_id' => $chatId]);
- return $this->transaction(function () use ($chatId, $corpId, $group, $groupInfo, $memberList) {
- if ($group) {
- $group->name = $groupInfo['name'];
- $group->owner = $groupInfo['owner'];
- $group->notice = $groupInfo['notice'] ?? '';
- $group->group_create_time = $groupInfo['create_time'];
- $group->member_num = count($memberList);
- $group->save();
- } else {
- $group = $this->dao->save([
- 'corp_id' => $corpId,
- 'chat_id' => $chatId,
- 'name' => $groupInfo['name'],
- 'owner' => $groupInfo['owner'],
- 'notice' => $groupInfo['notice'] ?? '',
- 'member_num' => count($memberList),
- 'group_create_time' => $groupInfo['create_time'],
- 'status' => $groupInfo['status'] ?? 0,
- ]);
- }
- $this->saveMember($memberList, $group->id, $group->member_num);
- return $group->id;
- });
- }
- /**
- * @param array $where
- * @return array
- */
- public function getList(array $where)
- {
- [$page, $limit] = $this->getPageValue();
- $where['timeKey'] = 'group_create_time';
- $where['status'] = [0, 2, 3];
- $list = $this->dao->getDataList($where, ['*'], $page, $limit, 'group_create_time', [
- 'ownerInfo' => function ($query) {
- $query->field(['userid', 'name']);
- },
- ]);
- //提取管理员数据
- $adminUserId = [];
- foreach ($list as $item) {
- $adminUserId = array_merge($adminUserId, $item['admin_list'] ?? []);
- }
- $adminUserId = array_merge(array_unique(array_filter($adminUserId)));
- if ($adminUserId) {
- /** @var WorkMemberServices $memberService */
- $memberService = app()->make(WorkMemberServices::class);
- $adminUserList = $memberService->getColumn([
- ['userid', 'in', $adminUserId],
- ], 'name', 'userid');
- foreach ($list as &$item) {
- $newAdminUser = [];
- if (!empty($item['admin_list'])) {
- foreach ($adminUserList as $key => $value) {
- if (in_array($key, $item['admin_list'])) {
- $newAdminUser[] = ['name' => $value, 'userid' => $key];
- }
- }
- }
- $item['admin_user_list'] = $newAdminUser;
- }
- }
- $count = $this->dao->count();
- return compact('list', 'count');
- }
- /**
- * 企业微信客户群变动
- * @param array $payload
- * @throws DataNotFoundException
- * @throws DbException
- * @throws ModelNotFoundException
- */
- public function updateGroupChat(array $payload)
- {
- $corpId = $payload['ToUserName'];
- $chatId = $payload['ChatId'];
- $groupInfo = $this->dao->get(['corp_id' => $corpId, 'chat_id' => $chatId]);
- if (!$groupInfo) {
- $groupId = $this->saveWorkGroupChat($corpId, $chatId);
- $groupInfo = $this->dao->get($groupId);
- }
- $response = Work::getGroupChat($chatId);
- if (0 !== $response['errcode']) {
- throw new ValidateException($response['errmsg'] ?? '企业微信查询群详情失败');
- }
- $groupChat = $response['group_chat'] ?? [];
- $memberList = $groupChat['member_list'];
- /** @var WorkGroupChatStatisticServices $statisticService */
- $statisticService = app()->make(WorkGroupChatStatisticServices::class);
- $this->transaction(function () use ($payload, $groupInfo, $groupChat, $memberList, $statisticService) {
- switch ($payload['UpdateDetail']) {
- case 'add_member':
- $groupInfo->member_num++;
- $this->saveMember($memberList, $groupInfo->id, $groupInfo->member_num, true);
- $statisticService->saveOrUpdate($groupInfo->id, true, false, $groupInfo->member_num, $groupInfo->retreat_group_num);
- break;
- case 'del_member':
- $groupInfo->member_num--;
- $groupInfo->retreat_group_num++;
- $this->saveMember($memberList, $groupInfo->id, $groupInfo->member_num, false);
- $statisticService->saveOrUpdate($groupInfo->id, false, true, $groupInfo->member_num, $groupInfo->retreat_group_num);
- break;
- case 'change_owner':
- $groupInfo->owner = $groupChat['owner'];
- break;
- case 'change_name':
- $groupInfo->name = $groupChat['name'];
- break;
- case 'change_notice':
- $groupInfo->notice = $groupChat['notice'];
- break;
- }
- if (!empty($groupChat['admin_list'])) {
- $groupInfo->admin_list = json_encode(array_column($groupChat['admin_list'], 'userid'));
- }
- $groupInfo->save();
- });
- }
- /**
- * 保存群成员
- * @param array $memberList
- * @param int $groupId
- * @param int $sum
- * @param bool $plus
- * @return mixed
- */
- public function saveMember(array $memberList, int $groupId, int $sum = 0, bool $plus = false)
- {
- $data = [];
- /** @var WorkGroupChatMemberServices $chatMemberService */
- $chatMemberService = app()->make(WorkGroupChatMemberServices::class);
- $newUserIds = array_column($memberList, 'userid');
- $userids = $chatMemberService->getColumn(['group_id' => $groupId], 'userid');
- $unUserIds = array_diff($userids, $newUserIds);
- $labelList = [];
- foreach ($memberList as $item) {
- $item['group_id'] = $groupId;
- $state = $item['state'] ?? '';
- if (isset($item['state'])) {
- unset($item['state']);
- }
- $item['invitor_userid'] = $item['invitor']['userid'] ?? '';
- $unionid = $item['unionid'] ?? '';
- unset($item['invitor'], $item['unionid']);
- if ($chatMemberService->count(['group_id' => $groupId, 'userid' => $item['userid']])) {
- $chatMemberService->update(['group_id' => $groupId, 'userid' => $item['userid']], [
- 'type' => $item['type'],
- 'unionid' => $unionid,
- 'chat_sum' => $sum,
- 'status' => 1,
- 'join_time' => $item['join_time'],
- 'join_scene' => $item['join_scene'],
- 'invitor_userid' => $item['invitor_userid'],
- 'group_nickname' => $item['group_nickname'],
- ]);
- } else {
- if ($state) {
- $labelList[] = ['userid' => $item['userid'], 'type' => $item['type'], 'state' => $state];
- }
- $item['unionid'] = $unionid;
- $item['chat_sum'] = $sum;
- $item['state'] = $state;
- $item['create_time'] = time();
- $data[] = $item;
- }
- }
- if ($data) {
- $chatMemberService->saveAll($data);
- //如果没有客户信息同步客户信息
- /** @var WorkClientServices $clientService */
- $clientService = app()->make(WorkClientServices::class);
- $corpId = app()->make(WorkConfig::class)->get('corpId');
- foreach ($data as $item) {
- if (2 == $item['type'] && $clientService->count(['external_userid' => $item['userid']])) {
- WorkClientJob::dispatchDo('saveClientInfo', [$corpId, $item['userid'], '']);
- }
- }
- }
- if ($unUserIds) {
- $chatMemberService->update([
- ['userid', 'in', $unUserIds]
- ], ['status' => 0]);
- }
- return true;
- }
- /**
- * 解散客户群
- * @param string $corpId
- * @param string $chatId
- * @return mixed
- * @throws DataNotFoundException
- * @throws DbException
- * @throws ModelNotFoundException
- */
- public function dismissGroupChat(string $corpId, string $chatId)
- {
- $groupChat = $this->dao->get(['corp_id' => $corpId, 'chat_id' => $chatId], ['id']);
- if (!$groupChat) {
- throw new ValidateException('没有查询到群');
- }
- return $this->transaction(function () use ($groupChat) {
- /** @var WorkGroupChatMemberServices $chatMemberService */
- $chatMemberService = app()->make(WorkGroupChatMemberServices::class);
- $chatMemberService->delete(['group_id' => $groupChat->id]);
- return $groupChat->delete();
- });
- }
- /**
- * 群统计
- * @param int $id
- * @param string $time
- * @return array
- */
- public function getChatStatistics(int $id, string $time)
- {
- /** @var WorkGroupChatMemberServices $chatMemberService */
- $chatMemberService = app()->make(WorkGroupChatMemberServices::class);
- $data = [
- 'toDaySum' => $chatMemberService->getToDaySum($id),
- 'toDayReturn' => $chatMemberService->getToDayReturn($id),
- 'groupChatSum' => $this->dao->value(['id' => $id], 'member_num'),
- 'groupChatReturnSum' => $this->dao->value(['id' => $id], 'retreat_group_num')
- ];
- $data['groupChatList'] = $chatMemberService->getChatMemberStatistics($id, 'join_time', ['count(*) as sum'], 1, $time);
- $data['groupChatReturnList'] = $chatMemberService->getChatMemberStatistics($id, 'join_time', ['count(*) as sum'], 0, $time);
- return $data;
- }
- /**
- * 群成员统计
- * @param int $id
- * @param string $time
- * @return array
- */
- public function getChatStatisticsList(int $id, string $time)
- {
- [$page, $limit] = $this->getPageValue();
- /** @var WorkGroupChatMemberServices $chatMemberService */
- $chatMemberService = app()->make(WorkGroupChatMemberServices::class);
- $newCount = $chatMemberService->getChatMemberStatisticsCount($id, 1, $time);
- $returnCount = $chatMemberService->getChatMemberStatisticsCount($id, 0, $time);
- $SumCount = $newCount > $returnCount ? $newCount : $returnCount;
- $groupChatList = $chatMemberService->getChatMemberStatistics($id, 'join_time', ['count(*) as sum', 'chat_sum', 'retreat_chat_num'], 1, $time, $page, $limit);
- $groupChatReturnList = $chatMemberService->getChatMemberStatistics($id, 'join_time', ['count(*) as retreat_sum'], 0, $time, $page, $limit);
- $count = ($rCount = count($groupChatReturnList)) > ($count = count($groupChatList)) ? $rCount : $count;
- $data = [];
- for ($i = 0; $i < $count; $i++) {
- $data[] = [
- 'time' => $groupChatList[$i]['time'] ?? $groupChatReturnList[$i]['time'] ?? '',
- 'sum' => $groupChatList[$i]['sum'] ?? 0,
- 'retreat_chat_num' => $groupChatList[$i]['retreat_chat_num'] ?? 0,
- 'chat_sum' => $groupChatList[$i]['chat_sum'] ?? 0,
- 'retreat_sum' => $groupChatReturnList[$i]['retreat_sum'] ?? 0,
- ];
- }
- return ['list' => $data, 'count' => $SumCount];
- }
- /**
- * @param string $chatId
- * @param string $corpId
- * @return array
- * @throws DataNotFoundException
- * @throws DbException
- * @throws ModelNotFoundException
- */
- public function getGroupInfo(string $chatId, string $corpId)
- {
- $groupInfo = $this->dao->get(['chat_id' => $chatId, 'corp_id' => $corpId]);
- if (!$groupInfo) {
- throw new ValidateException('客户群未查到');
- }
- /** @var WorkGroupChatMemberServices $service */
- $service = app()->make(WorkGroupChatMemberServices::class);
- $groupInfo['todaySum'] = $service->getToDaySum($groupInfo->id);
- $groupInfo['todayReturnSum'] = $service->getToDayReturn($groupInfo->id);
- return $groupInfo->toArray();
- }
- }
|