Files
code-bang/backend/application/common/service/DemandGroupChatService.php
T
2026-09-29 16:24:19 +08:00

213 lines
6.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace app\common\service;
use app\common\model\demand\group\Chat;
use app\common\traits\ServiceTrait;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use think\Log;
class DemandGroupChatService
{
use ServiceTrait;
/** @var Chat */
public static $Model = Chat::class;
// 竞标状态
const STATUS_BIDDING_NO = 0; //无
const STATUS_BIDDING_ONGOING = 1; //竞标中
const STATUS_BIDDING_WIN = 2; //中标
const STATUS_BIDDING_FAILED = 3; //未中标
const BIDDING_STATUS_MAP = [
self::STATUS_BIDDING_NO => '无',
self::STATUS_BIDDING_ONGOING => '竞标中',
self::STATUS_BIDDING_WIN => '中标',
self::STATUS_BIDDING_FAILED => '未中标',
];
// 竞标状态
const STATUS_PROCESS_NO = 0; //未处理
const STATUS_PROCESS_ONGOING = 1; //待确认
const STATUS_PROCESS_CONFIRMED = 2; //已确认
const STATUS_PROCESS_FAILED = 3; //已拒绝
const STATUS_PROCESS_TIMEOUT = 4; //超时弃权
const PROCESS_STATUS_MAP = [
self::STATUS_PROCESS_NO => '未处理',
self::STATUS_PROCESS_ONGOING => '待确认',
self::STATUS_PROCESS_CONFIRMED => '已确认',
self::STATUS_PROCESS_FAILED => '已拒绝',
self::STATUS_PROCESS_TIMEOUT => '超时弃权',
];
/**
* 保存客户群列表(只补充未入库的群,可重复执行)
* @return int 新增数量
* @throws GuzzleException
*/
public static function syncList(): int
{
$scene = 2;
$state = '';
$group_chat_list = WorkWeChatService::groupChatList();
$dataList = [];
foreach ($group_chat_list as $chat) {
$chat_id = $chat['chat_id'] ?? '';
if (!$chat_id) {
continue;
}
$groupChatInfo = WorkWeChatService::groupChatInfo($chat_id);
$dataList[] = [
'demand_id' => 0,
'chat_id' => $chat_id,
'name' => $groupChatInfo['name'] ?? '',
'config_id' => '',
'qr_code' => '',
'scene' => $scene,
'state' => $state,
];
}
//群名为空时不再排序,避免空列表导致报错
if (!$dataList) {
Log::warning(__METHOD__ . ' 企业微信未返回任何客户群,请检查群主配置与接口权限');
return 0;
}
usort($dataList, function ($a, $b) {
return (int)filter_var($a['name'], FILTER_SANITIZE_NUMBER_INT) <=> (int)filter_var($b['name'], FILTER_SANITIZE_NUMBER_INT);
});
$chatIdList = self::where('chat_id', '<>', '')->column('chat_id');
$dataList = array_filter($dataList, function ($value) use ($chatIdList) {
return !in_array($value['chat_id'], $chatIdList);
});
if (!$dataList) {
return 0;
}
(new self::$Model)->saveAll($dataList);
return count($dataList);
}
/**
* 分配一个空闲群给需求,并生成(或刷新)二维码
* @param $demand_id
* @param bool $refresh
* @return mixed
* @throws
*/
public static function updateQrCode($demand_id, bool $refresh = false)
{
//分配一个未使用的群
$info = self::getOne(['demand_id' => 0], [], ['id']);
if (!$info) {
Log::error(__METHOD__ . ' 群池已空,无法为需求分配沟通群,demand_id:' . $demand_id);
return false;
}
$info->demand_id = $demand_id;
self::refreshQrCode($info, $refresh);
return $info->save();
}
/**
* 重新生成群的入群二维码
* 失败只记录日志并返回 false,不抛异常,避免影响确认接单等主流程
* @param Chat|\think\Model $info
* @param bool $refresh 已有二维码时是否强制刷新
* @return bool
* @throws GuzzleException
*/
public static function refreshQrCode($info, bool $refresh = false): bool
{
if ($info->qr_code && !$refresh) {
return true;
}
//更新config_id,防止设置群聊邀请确认后不生效
$config_id = WorkWeChatService::groupChatAddJoinWay([$info['chat_id']]);
if (!$config_id) {
Log::error(__METHOD__ . ' 生成入群方式失败,chat_id:' . $info['chat_id']);
return false;
}
$join_way = WorkWeChatService::groupChatGetJoinWay($config_id);
if (empty($join_way['qr_code'])) {
Log::error(__METHOD__ . ' 获取群二维码失败,config_id:' . $config_id);
return false;
}
$info->config_id = $config_id;
$info->qr_code = $join_way['qr_code'];
return true;
}
/**
* 刷新所有已分配群的二维码
* @return array
* @throws GuzzleException
*/
public static function refreshAll(): array
{
$list = self::where('demand_id', '>', 0)->select();
$result = ['total' => 0, 'success' => 0, 'fail' => 0, 'failDemandIds' => []];
foreach ($list as $item) {
$result['total']++;
if (self::refreshQrCode($item, true) && $item->save()) {
$result['success']++;
} else {
$result['fail']++;
$result['failDemandIds'][] = $item->demand_id;
}
}
return $result;
}
/**
* 刷新指定需求群的二维码
* @param $demand_id
* @return bool
* @throws GuzzleException
*/
public static function refreshByDemand($demand_id)
{
$info = self::getOne(['demand_id' => $demand_id]);
if (!$info) {
Log::error(__METHOD__ . ' 该需求没有已分配的沟通群,demand_id:' . $demand_id);
return false;
}
if (!self::refreshQrCode($info, true)) {
return false;
}
return (bool)$info->save();
}
/**
* 回收需求占用的群,归还群池
* @param $demand_id
* @return bool
*/
public static function recycle($demand_id)
{
$info = self::getOne(['demand_id' => $demand_id]);
if (!$info) {
return false;
}
$info->demand_id = 0;
$info->config_id = '';
//旧二维码随需求作废,下次分配时重新生成
$info->qr_code = '';
return (bool)$info->save();
}
/**
* 群池状态
* @return array
*/
public static function stat(): array
{
return [
'total' => self::$Model::count(),
'free' => self::where('demand_id', 0)->count(),
'used' => self::where('demand_id', '>', 0)->count(),
'no_qrcode' => self::where('qr_code', '')->count(),
];
}
}