徐总多门店
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
jiuhaoshenghuo/app/services/work/WorkChannelCodeServices.php

373 lines
13 KiB

2 months ago
<?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\WorkChannelCodeDao;
use app\services\BaseServices;
use app\services\user\label\UserLabelServices;
use crmeb\services\wechat\Work;
use crmeb\traits\service\ContactWayQrCode;
use crmeb\traits\ServicesTrait;
use think\exception\ValidateException;
/**
* 渠道码
* Class WorkChannelCodeServices
* @package app\services\work
* @mixin WorkChannelCodeDao
*/
class WorkChannelCodeServices extends BaseServices
{
use ServicesTrait, ContactWayQrCode;
/**
* WorkChannelCodeServices constructor.
* @param WorkChannelCodeDao $dao
*/
public function __construct(WorkChannelCodeDao $dao)
{
$this->dao = $dao;
}
/**
* 获取渠道二维码列表
* @param array $where
* @return array
*/
public function getList(array $where)
{
[$page, $limit] = $this->getPageValue();
$list = $this->dao->getDataList($where, ['*'], $page, $limit, 'create_time', ['category' => function ($query) {
$query->field(['id', 'name']);
}]);
//获取标签
$labelIds = [];
foreach ($list as $item) {
$labelIds = array_merge($labelIds, $item['label_id']);
}
$labelIds = array_merge(array_unique(array_filter($labelIds)));
$labelList = [];
if ($labelIds) {
/** @var UserLabelServices $labelServices */
$labelServices = app()->make(UserLabelServices::class);
$labelList = $labelServices->getColumn([
['tag_id', 'in', $labelIds]
], 'label_name', 'tag_id');
}
foreach ($list as &$item) {
foreach ($labelList as $key => $value) {
if (in_array($key, $item['label_id'])) {
$item['label_name'][] = $value;
}
}
}
$count = $this->dao->count($where);
return compact('list', 'count');
}
/**
* 获取渠道码详情
* @param int $id
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getChannelInfo(int $id)
{
$channelInfo = $this->dao->get($id, ['*'], ['cycle', 'useridLimit' => function ($query) {
$query->with(['member']);
}]);
if (!$channelInfo) {
throw new ValidateException('没有查询到渠道二维码信息');
}
/** @var WorkMemberServices $make */
$make = app()->make(WorkMemberServices::class);
//重组周期数据
if (!empty($channelInfo['cycle'])) {
$userIds = [];
foreach ($channelInfo['cycle'] as $item) {
$userIds = array_merge($userIds, $item['userids']);
}
if ($userIds) {
$userIds = array_merge(array_unique(array_filter($userIds)));
$userList = $make->getColumn([['userid', 'in', $userIds]], 'name', 'userid');
foreach ($channelInfo['cycle'] as &$item) {
$userItem = [];
foreach ($userList as $key => $value) {
if (in_array($key, $item['userids'])) {
$userItem[] = ['name' => $value, 'userid' => $key];
}
}
$item['userItem'] = $userItem;
}
}
}
$channelInfo = $channelInfo->toArray();
$channelInfo['presentUseUserIds'] = $this->getPresentUseUserIds((int)$channelInfo['type'], $channelInfo['cycle'] ?? [], $channelInfo['useridLimit'] ?? [], [
'reserve_userid' => $channelInfo['reserve_userid'],
'userids' => $channelInfo['userids'],
'code_id' => $channelInfo['id'],
'add_upper_limit' => $channelInfo['add_upper_limit'],
]);
$channelInfo['presentUseUserList'] = $make->getColumn([['userid', 'in', $channelInfo['presentUseUserIds']]], 'name');
$channelInfo['reserve_user_list'] = $make->getColumn([['userid', 'in', $channelInfo['reserve_userid']]], 'name');
$channelInfo['user_list'] = $make->getColumn([['userid', 'in', $channelInfo['userids']]], 'name,userid,avatar');
return $channelInfo;
}
/**
* 保存和修改渠道二维码
* @param array $data
* @param int $id
* @return mixed
*/
public function saveChanne(array $data, int $id = 0)
{
$data['type'] = (int)$data['type'];
$cycle = $data['cycle'];
$useridLimit = $data['useridLimit'];
unset($data['cycle'], $data['useridLimit']);
//验证数据
if (1 == $data['type']) {
if (!count($cycle)) {
throw new ValidateException('至少设置一个周期');
}
$this->checkEmployee($cycle);
} else {
if (!$data['userids']) {
throw new ValidateException('必须选择一个成员');
}
if (count($data['userids']) > 100) {
throw new ValidateException('选择的成员不能大于100个');
}
}
//验证欢迎语
$this->checkWelcome($data['welcome_words'], (int)$data['welcome_type']);
/** @var WorkChannelCycleServices $cycleService */
$cycleService = app()->make(WorkChannelCycleServices::class);
/** @var WorkChannelLimitServices $limitService */
$limitService = app()->make(WorkChannelLimitServices::class);
//保存数据
$id = $this->transaction(function () use ($cycle, $id, $data, $cycleService, $useridLimit, $limitService) {
$configId = null;
if ($id) {
$this->dao->update($id, $data);
$configId = $this->dao->value(['id' => $id], 'config_id');
} else {
$data['create_time'] = time();
$res = $this->dao->save($data);
if (!$res) {
throw new ValidateException('保存失败');
}
$id = $res->id;
}
$newCycle = $cycle;
foreach ($cycle as &$item) {
$item['channel_id'] = $id;
$item['userids'] = json_encode($item['userids']);
$item['wokr_time'] = json_encode($item['wokr_time']);
}
foreach ($useridLimit as &$item) {
$item['channel_id'] = $id;
}
$cycleService->delete(['channel_id' => $id]);
$cycleService->saveAll($cycle);
$limitService->delete(['channel_id' => $id]);
$limitService->saveAll($useridLimit);
//提取在线成员生成二维码
$userIds = $this->getPresentUseUserIds((int)$data['type'], $newCycle, $useridLimit, [
'reserve_userid' => $data['reserve_userid'],
'userids' => $data['userids'],
'code_id' => $id,
'add_upper_limit' => $data['add_upper_limit'],
]);
$this->handleQrCode((int)$id, $userIds, !!$data['skip_verify'], $configId);
return $id;
});
return $id;
}
/**
* 获取当前时间内值班的成员userid
* @param int $type
* @param array $cycle
* @param array $useridLimit
* @param array $option
* @return array|mixed
*/
public function getPresentUseUserIds(int $type, array $cycle, array $useridLimit, array $option = [])
{
$addUpperLimit = (int)($option['add_upper_limit'] ?? 0);
if (0 !== $type) {
$newUserIdLimit = [];
foreach ($useridLimit as $item) {
$newUserIdLimit[$item['userid']] = $item;
}
$userIds = $this->cycleByUserid($cycle, $newUserIdLimit, $option['code_id'], $addUpperLimit);
} else {
//限制添加成员
if (1 === $addUpperLimit) {
$userIds = $this->addClientLimit($option['userids'] ?? [], $useridLimit, $option['code_id']);
} else {
$userIds = $option['userids'] ?? [];
}
}
if (!$userIds) {
$userIds = $option['reserve_userid'] ?? [];
}
return $userIds;
}
/**
* 检测成员限制
* @param array $cycle
*/
public function checkEmployee(array $cycle)
{
$week = [];
foreach ($cycle as $item) {
foreach ($item['wokr_time'] as $num) {
$week[$num] = array_merge(($week[$num] ?? []), $item['userids']);
}
}
foreach ($week as $item) {
if (count($item) > 100) {
throw new ValidateException('周期内每个联系方式最多配置100个使用成员');
}
}
}
/**
* 根据周期规则获取当前值班成员userid
* @param array $cycle
* @param array $useridLimit
* @param int $codeId
* @param int $addUpperLimit
* @return array
*/
public function cycleByUserid(array $cycle, array $useridLimit = [], int $codeId = 0, int $addUpperLimit = 0)
{
$userids = [];
$weekNam = date('w');
$nowHon = date('H:i');
foreach ($cycle as $item) {
//查询出当前周期内工作的值班人员
if (in_array($weekNam, $item['wokr_time']) && $item['start_time'] <= $nowHon && $nowHon <= $item['end_time']) {
$userids = array_merge($userids, $item['userids']);
}
//24小时值班人员
if (in_array($weekNam, $item['wokr_time']) && $item['start_time'] == $item['end_time']) {
$userids = array_merge($userids, $item['userids']);
}
}
//每日值班人数大于100的需要使用备用人员
$userids = array_merge(array_unique($userids));
if ($userids && count($userids) > 100) {
return [];
}
//不限制添加客户上限
if (0 === $addUpperLimit) {
return $userids;
}
return $this->addClientLimit($userids, $useridLimit, $codeId);
}
/**
* 获取添加员工上限
* @param array $userids
* @param array $useridLimit
* @param int $codeId
* @return array
*/
protected function addClientLimit(array $userids, array $useridLimit, int $codeId)
{
/** @var WorkClientFollowServices $followService */
$followService = app()->make(WorkClientFollowServices::class);
$userCount = $followService->userIdByCilentCount($userids, $codeId);
if (!$userCount) {
return $userids;
}
$useridLimitNew = [];
foreach ($useridLimit as $value) {
$useridLimitNew[$value['userid']] = $value;
}
$returnUserId = [];
//限制员工每日添加客户个数
foreach ($userids as $userid) {
foreach ($userCount as $item) {
if ($userid == $item['userid'] && $useridLimitNew[$userid]['max'] > $item['sum']) {
$returnUserId[] = $userid;
}
}
}
return $returnUserId;
}
/**
* @param int $id
* @return mixed
*/
public function deleteChannel(int $id)
{
$configId = $this->dao->value(['id' => $id], 'config_id');
return $this->transaction(function () use ($id, $configId) {
if ($configId) {
Work::deleteQrCode($configId);
}
return $this->dao->destroy($id);
});
}
/**
* 执行生成渠道二维码
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function cronHandle()
{
$channelList = $this->dao->getDataList(['status' => 1, 'type' => 1], ['*'], 0, 0, null, ['cycle', 'useridLimit']);
foreach ($channelList as $item) {
//提取在线成员生成二维码
$userIds = $this->getPresentUseUserIds(
(int)$item['type'],
$item['cycle'] ?? [],
$item['useridLimit'] ?? [],
[
'reserve_userid' => $item['reserve_userid'],
'userids' => $item['userids'],
'code_id' => $item['id'],
'add_upper_limit' => $item['add_upper_limit'],
]
);
if ($userIds) {
$this->handleQrCode((int)$item['id'], $userIds, !!$item['skip_verify'], $item['config_id']);
}
}
return true;
}
}