ts
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
namespace app\common\utils\approval\service\traits;
|
||||
|
||||
use support\Db;
|
||||
use support\exception\BusinessException;
|
||||
|
||||
trait ApprovalDiscussionTrait
|
||||
{
|
||||
/** 是否该实例参与者 */
|
||||
private function isParticipantOfInstance(int $instanceId, int $userId): bool
|
||||
{
|
||||
$inst = Db::table('approval_instances')->where('id', $instanceId)->first();
|
||||
if (!$inst) return false;
|
||||
if ((int)$inst->initiator_id === $userId) return true;
|
||||
|
||||
$inRecords = Db::table('approval_records')
|
||||
->where('instance_id', $instanceId)->where('approver_id', $userId)->exists();
|
||||
if ($inRecords) return true;
|
||||
|
||||
$inCc = Db::table('approval_ccs')
|
||||
->where('instance_id', $instanceId)->where('user_id', $userId)->exists();
|
||||
return $inCc;
|
||||
}
|
||||
|
||||
/** 是否该实例任一步的审批人 */
|
||||
private function isApproverOfInstance(int $instanceId, int $userId): bool
|
||||
{
|
||||
return Db::table('approval_records')
|
||||
->where('instance_id', $instanceId)
|
||||
->where('approver_id', $userId)
|
||||
->exists();
|
||||
}
|
||||
|
||||
/** 获取讨论受众 */
|
||||
private function getDiscussionAudienceUserIds(int $instanceId, bool $approversOnly, int $excludeUserId): array
|
||||
{
|
||||
$uids = [];
|
||||
if (!$approversOnly) {
|
||||
$inst = Db::table('approval_instances')->where('id', $instanceId)->first();
|
||||
if ($inst) $uids[] = (int)$inst->initiator_id;
|
||||
$ccs = Db::table('approval_ccs')->where('instance_id', $instanceId)->pluck('user_id')->toArray();
|
||||
foreach ($ccs as $u) $uids[] = (int)$u;
|
||||
}
|
||||
$approvers = Db::table('approval_records')
|
||||
->where('instance_id', $instanceId)
|
||||
->distinct()->pluck('approver_id')->toArray();
|
||||
foreach ($approvers as $u) $uids[] = (int)$u;
|
||||
|
||||
$uids = array_values(array_unique(array_filter($uids, fn($u) => $u !== $excludeUserId)));
|
||||
return $uids;
|
||||
}
|
||||
|
||||
/** 发表讨论 */
|
||||
public function postDiscussion(
|
||||
int $instanceId,
|
||||
int $userId,
|
||||
string $content,
|
||||
bool $isInternal = false,
|
||||
array $attachments = [],
|
||||
?string $userNameColumn = null
|
||||
): array {
|
||||
$content = trim($content);
|
||||
if ($content === '') throw new BusinessException('讨论内容不能为空');
|
||||
if (!$this->isParticipantOfInstance($instanceId, $userId)) {
|
||||
throw new BusinessException('无权参与该实例的讨论');
|
||||
}
|
||||
if ($isInternal && !$this->isApproverOfInstance($instanceId, $userId)) {
|
||||
throw new BusinessException('仅审批人可发布内部讨论');
|
||||
}
|
||||
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$id = Db::table('approval_discussions')->insertGetId([
|
||||
'instance_id' => $instanceId,
|
||||
'user_id' => $userId,
|
||||
'is_internal' => $isInternal ? 1 : 0,
|
||||
'content' => $content,
|
||||
'attachments' => empty($attachments) ? null : json_encode($attachments, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES),
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
|
||||
// 通知其他人
|
||||
$inst = Db::table('approval_instances')->where('id', $instanceId)->first();
|
||||
if ($inst) {
|
||||
$audience = $this->getDiscussionAudienceUserIds($instanceId, $isInternal, $userId);
|
||||
// 发言人姓名(可选)
|
||||
$speaker = (string)$userId;
|
||||
if ($userNameColumn) {
|
||||
$name = Db::table('user')->where('id', $userId)->value($userNameColumn);
|
||||
if ($name) $speaker = $name;
|
||||
}
|
||||
$snippet = function_exists('mb_strimwidth') ? mb_strimwidth($content, 0, 80, '...', 'UTF-8') : $content;
|
||||
$extra = ['note' => "【讨论】{$speaker}:{$snippet}"];
|
||||
|
||||
$this->sendNotification(
|
||||
$audience,
|
||||
(object)[
|
||||
'id' => (int)$inst->id,
|
||||
'flow_type' => (string)$inst->flow_type,
|
||||
'initiator_id' => (int)$inst->initiator_id,
|
||||
'form_data' => $inst->form_data,
|
||||
'biz_type' => (string)$inst->biz_type,
|
||||
'biz_id' => (string)$inst->biz_id,
|
||||
],
|
||||
'pending',
|
||||
false,
|
||||
$extra
|
||||
);
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => (int)$id,
|
||||
'instance_id' => $instanceId,
|
||||
'user_id' => $userId,
|
||||
'is_internal' => (bool)$isInternal,
|
||||
'content' => $content,
|
||||
'attachments' => $attachments,
|
||||
'created_at' => $now,
|
||||
];
|
||||
}
|
||||
|
||||
/** 获取讨论列表 */
|
||||
public function listDiscussions(int $instanceId, ?int $afterId = null, int $limit = 50, ?string $userNameColumn = null): array
|
||||
{
|
||||
$q = Db::table('approval_discussions as d')->where('d.instance_id', $instanceId);
|
||||
if ($afterId) $q->where('d.id', '>', $afterId);
|
||||
$q->orderBy('d.id', 'asc')->limit(max(1, min(200, $limit)));
|
||||
|
||||
if ($userNameColumn) {
|
||||
$rows = $q->leftJoin('user as u', 'd.user_id', '=', 'u.id')
|
||||
->select('d.*', Db::raw("u.`{$userNameColumn}` as user_name"))
|
||||
->get()->toArray();
|
||||
} else {
|
||||
$rows = $q->select('d.*')->get()->toArray();
|
||||
}
|
||||
|
||||
return array_map(function($r){
|
||||
return [
|
||||
'id' => (int)$r->id,
|
||||
'instance_id' => (int)$r->instance_id,
|
||||
'user_id' => (int)$r->user_id,
|
||||
'is_internal' => (bool)$r->is_internal,
|
||||
'content' => $r->content,
|
||||
'attachments' => $r->attachments ? json_decode($r->attachments, true) : [],
|
||||
'created_at' => $r->created_at,
|
||||
'updated_at' => $r->updated_at,
|
||||
'user_name' => property_exists($r, 'user_name') ? $r->user_name : null,
|
||||
];
|
||||
}, $rows);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user