Files
cunkebao_v3/Server/application/chukebao/controller/TransferController.php
Manus AI 5517457929 sync: 以本地为准同步全量变更至 GitHub
含四端需求文档、前端/后端/超管/触客宝迭代及部署脚本更新;未拉取远程。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-30 04:24:56 +08:00

208 lines
8.2 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\chukebao\controller;
use library\ResponseHelper;
use think\Db;
/**
* 模块 G · 转移申请(需求七 §7.7 · 需求九 §9.1
* 铁律:触客宝仅「申请」,执行须存客宝审批;不在前端直调即时 transfer。
* 统一写入存客宝真源表 ck_wechat_account_transfer与 cunkebao WechatAccountTransferController 同表,
* 故触客宝提交的申请可在存客宝 H5 审批列表直接出现并由其执行 allot
*/
class TransferController extends BaseController
{
private const SUPPORTED_TYPES = ['session', 'wechat_account', 'contact_group'];
/** 数字微信号账号 id → wechatId整号转移以 wechatId 为 targetId 口径,与 allot 一致) */
private function resolveWechatId(int $accountId): string
{
return (string)Db::table('s2_wechat_account')->where('id', $accountId)->value('wechatId');
}
private function createApply($type)
{
$companyId = (int)$this->getUserInfo('companyId');
$applicantUserId = (int)$this->getUserInfo('id');
$applicantName = (string)($this->getUserInfo('username') ?: '');
$toAccountId = trim((string)$this->request->param('toAccountId', $this->request->param('toKefuId', '')));
$reason = (string)$this->request->param('reason', '');
// targetId 口径wechat_account → wechatIdsession → wechatFriendIdcontact_group → groupId
if ($type === 'wechat_account') {
$accId = (int)$this->request->param('wechatAccountId', 0);
$targetId = $this->resolveWechatId($accId);
if ($targetId === '') {
return ResponseHelper::error('微信号不存在,无法转移', 400);
}
} elseif ($type === 'contact_group') {
$groupType = (int)$this->request->param('groupType', 1);
if ($groupType !== 1) {
return ResponseHelper::error('仅好友分组支持转移申请', 400);
}
$wechatAccountId = (int)$this->request->param('wechatAccountId', 0);
if ($wechatAccountId <= 0) {
return ResponseHelper::error('wechatAccountId 缺失', 400);
}
$targetId = (string)(int)$this->request->param('groupId', 0);
} else {
$targetId = (string)$this->request->param('wechatFriendId', 0);
}
if ($toAccountId === '' || $targetId === '' || $targetId === '0') {
return ResponseHelper::error('参数缺失(目标客服/对象)', 400);
}
// 校验目标客服归属同公司
$toAccount = Db::table('s2_company_account')
->where('id', $toAccountId)
->where('departmentId', $companyId)
->field('id, userName, realName, nickname')
->find();
$toAccountName = $toAccount
? (($toAccount['realName'] ?: $toAccount['nickname'] ?: $toAccount['userName']) ?: '')
: '';
$affected = 0;
try {
if ($type === 'session') {
$affected = 1;
} elseif ($type === 'wechat_account') {
$affected = (int)Db::table('s2_wechat_friend')->where('ownerWechatId', $targetId)->count();
} elseif ($type === 'contact_group') {
$wechatAccountId = (int)$this->request->param('wechatAccountId', 0);
$ownerWechatId = $this->resolveWechatId($wechatAccountId);
if ($ownerWechatId === '') {
return ResponseHelper::error('微信号不存在,无法发起分组转移', 400);
}
$affected = (int)Db::table('s2_wechat_friend')
->where('ownerWechatId', $ownerWechatId)
->where('groupIds', (int)$targetId)
->where('isDeleted', 0)
->count();
}
} catch (\Throwable $e) {
}
if ($type === 'contact_group' && $affected <= 0) {
return ResponseHelper::error('本分组暂无好友,无法发起转移', 400);
}
$now = time();
$applyId = Db::name('wechat_account_transfer')->insertGetId([
'companyId' => $companyId,
'type' => $type,
'targetId' => $targetId,
'targetName' => (string)$this->request->param('targetName', ''),
'toAccountId' => $toAccountId,
'toAccountName' => $toAccountName,
'applicantUserId' => $applicantUserId,
'applicantName' => $applicantName,
'reason' => $this->buildReason($type, $reason),
'affectedFriendCount' => $affected,
'status' => 'pending',
'createTime' => $now,
'updateTime' => $now,
]);
return ResponseHelper::success([
'applyId' => (int)$applyId,
'status' => 'pending',
'affectedFriendCount' => $affected,
], '转移申请已提交,等待存客宝审批');
}
/** POST /v1/kefu/wechat-account/transfer/apply */
public function applyWechatAccount()
{
return $this->createApply('wechat_account');
}
/** POST /v1/kefu/session/transfer/apply */
public function applySession()
{
return $this->createApply('session');
}
/** POST /v1/kefu/transfer/apply */
public function apply()
{
$type = trim((string)$this->request->param('type', ''));
if (!in_array($type, self::SUPPORTED_TYPES, true)) {
return ResponseHelper::error('转移类型不支持', 400);
}
return $this->createApply($type);
}
/** GET /v1/kefu/wechat-account/transfer/status?applyId= */
public function status()
{
$companyId = (int)$this->getUserInfo('companyId');
$applyId = (int)$this->request->param('applyId', 0);
if (!$applyId) {
return ResponseHelper::error('applyId 缺失', 400);
}
$row = Db::name('wechat_account_transfer')
->where('companyId', $companyId)
->where('id', $applyId)
->find();
if (!$row) {
return ResponseHelper::error('申请不存在', 404);
}
return ResponseHelper::success([
'applyId' => (int)$row['id'],
'status' => $row['status'],
'reason' => $row['reviewComment'] ?? '',
'executedCount' => (int)($row['executedCount'] ?? 0),
]);
}
/** GET /v1/kefu/wechatGroup/transfer/preview */
public function groupPreview()
{
$groupType = (int)$this->request->param('groupType', 1);
$groupId = (int)$this->request->param('groupId', 0);
$wechatAccountId = (int)$this->request->param('wechatAccountId', 0);
if ($groupType !== 1) {
return ResponseHelper::error('仅好友分组支持预览', 400);
}
if ($groupId <= 0 || $wechatAccountId <= 0) {
return ResponseHelper::error('参数缺失groupId/wechatAccountId', 400);
}
$ownerWechatId = $this->resolveWechatId($wechatAccountId);
if ($ownerWechatId === '') {
return ResponseHelper::error('微信号不存在', 404);
}
$companyId = (int)$this->getUserInfo('companyId');
$groupName = (string)Db::table('s2_chat_groups')
->where('companyId', $companyId)
->where('id', $groupId)
->value('groupName');
$count = (int)Db::table('s2_wechat_friend')
->where('ownerWechatId', $ownerWechatId)
->where('groupIds', $groupId)
->where('isDeleted', 0)
->count();
return ResponseHelper::success([
'groupId' => $groupId,
'groupType' => 1,
'groupName' => $groupName ?: '未命名分组',
'count' => $count,
]);
}
private function buildReason(string $type, string $reason): string
{
if ($type !== 'contact_group') {
return $reason;
}
$payload = [
'rawReason' => $reason,
'groupType' => (int)$this->request->param('groupType', 1),
'groupId' => (int)$this->request->param('groupId', 0),
'wechatAccountId' => (int)$this->request->param('wechatAccountId', 0),
];
return json_encode($payload, JSON_UNESCAPED_UNICODE);
}
}