diff --git a/app/admin/controller/ApprovalRecordsController.php b/app/admin/controller/ApprovalRecordsController.php index 4e963ea..1bf914e 100644 --- a/app/admin/controller/ApprovalRecordsController.php +++ b/app/admin/controller/ApprovalRecordsController.php @@ -47,7 +47,9 @@ class ApprovalRecordsController extends BaseController 'step_index' => $record['step_index'], 'action' => $record['action'], - 'status' => SysDictItem::where('item_value', $record['status'])->where('status', 1)->value('item_label'), + 'action_desc' => SysDictItem::where('item_value', $record['action'])->where('status', 1)->value('item_label'), + 'status' => $record['status'], + 'status_desc' => SysDictItem::where('item_value', $record['status'])->where('status', 1)->value('item_label'), 'comment' => $record['comment'], 'approved_at' => $record['approved_at'], diff --git a/app/common/service/StockOrdersService.php b/app/common/service/StockOrdersService.php index 6a6d6b6..d936e5d 100644 --- a/app/common/service/StockOrdersService.php +++ b/app/common/service/StockOrdersService.php @@ -11,7 +11,6 @@ use app\common\model\StockOrders; use app\common\model\SysCurrency; use support\Request; use app\common\model\User; -use support\exception\BusinessException; use support\Db; class StockOrdersService @@ -63,6 +62,10 @@ class StockOrdersService } $config['order']['id'] = 'desc'; + + // $config['dataLimit']['type'] = 'relation'; + // $config['dataLimit']['userId'] = $request->user->uid; + // $config['dataLimit']['userField'] = 'salesperson_id'; break; case 'print': $config['where']['id'] = $p['id']; diff --git a/app/common/utils/approval/service/ApprovalFlowService.php b/app/common/utils/approval/service/ApprovalFlowService.php index b794532..9916b6e 100644 --- a/app/common/utils/approval/service/ApprovalFlowService.php +++ b/app/common/utils/approval/service/ApprovalFlowService.php @@ -112,7 +112,7 @@ class ApprovalFlowService if ((int)$instance->current_step !== $idx) { // return ['status' => 'noop', 'reason' => 'not_current_step', 'current_step' => (int)$instance->current_step]; // throw new BusinessException("非当前步骤"); - return ['status' => 'noop', 'msg' => '非当前步骤']; + return ['status' => 'noop', 'msg' => '非当前审批']; } // return ['status' => 'noop', 'reason' => 'no_pending_record']; return ['status' => 'noop', 'msg' => '无待处理记录']; @@ -136,7 +136,7 @@ class ApprovalFlowService if ($outcome === 'pending') { // return ['status' => 'step_pending']; - return ['status' => 'step_pending', 'msg' => '步骤待定']; + return ['status' => 'step_pending', 'msg' => '审批待定']; } // 3) 有结论:关闭本步其余 pending @@ -386,10 +386,11 @@ class ApprovalFlowService $resolved = array_unique(array_filter(array_map('intval', $resolved))); if ($avoidSelf) { - $resolved = array_values(array_filter($resolved, fn($id) => $id !== (int)$instance->initiator_id)); + // $resolved = array_values(array_filter($resolved, fn($id) => $id !== (int)$instance->initiator_id)); + $resolved = array_values($resolved); } if (empty($resolved)) { - throw new BusinessException("步骤未解析到任何审批人"); + throw new BusinessException("未解析到任何审批人"); } return $resolved; } diff --git a/app/common/utils/approval/service/ApprovalFlowService_bak.php b/app/common/utils/approval/service/ApprovalFlowService_bak.php deleted file mode 100644 index f988a48..0000000 --- a/app/common/utils/approval/service/ApprovalFlowService_bak.php +++ /dev/null @@ -1,751 +0,0 @@ -where('type', $flowType) - ->where('is_active', 1) - ->first(); - - if (!$flow) { - throw new BusinessException("审批流程未找到或已停用: {$flowType}"); - } - - $steps = json_decode($flow->steps, true); - if (!is_array($steps) || empty($steps)) { - throw new BusinessException("流程步骤配置错误"); - } - - // 2) 寻找首个有效步骤索引(考虑条件) - $firstIndex = $this->getNextStepIndex($steps, $formData, -1); - if ($firstIndex === null) { - throw new BusinessException("未找到可执行的审批步骤"); - } - $firstStep = $steps[$firstIndex]; - - // 3) 计算实例截止时间(实例级,可扩展到步骤级) - $deadlineAt = null; - if (($flow->timeout_hours ?? 0) > 0) { - $deadlineAt = date('Y-m-d H:i:s', time() + $flow->timeout_hours * 3600); - } - - // 4) 创建审批实例 - $now = date('Y-m-d H:i:s'); - $instanceId = Db::table('approval_instances')->insertGetId([ - 'flow_type' => $flowType, - 'biz_type' => $bizType, - 'biz_id' => $bizId, - 'form_data' => json_encode($formData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), - 'initiator_id' => $initiatorId, - 'status' => 'processing', - 'current_step' => $firstIndex, - 'deadline_at' => $deadlineAt, - 'created_at' => $now, - 'updated_at' => $now, - ]); - - // 5) 创建首步待办 - $instance = (object)[ - 'id' => $instanceId, - 'flow_type' => $flowType, - 'form_data' => json_encode($formData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), - 'initiator_id' => $initiatorId, - 'current_step' => $firstIndex, - 'status' => 'processing', - ]; - $approverIds = $this->resolveApprovers($firstStep, $instance, true); - - foreach ($approverIds as $uid) { - // 唯一键会防重复 - $this->insertApprovalRecord($instanceId, $firstIndex, $uid); - } - - // 6) 通知审批人 & 抄送 - $this->sendNotification($approverIds, $instance, 'pending', false); - $this->notifyCCs($firstStep, $instance, 'pending'); - - return ['instance_id' => $instanceId]; - }); - } - - /** - * 执行审批 - */ - public function approve(int $instanceId, int $approverId, string $action, string $comment = '') - { - if (!in_array($action, ['approve', 'reject'], true)) { - throw new BusinessException("无效的审批操作"); - } - - return Db::transaction(function () use ($instanceId, $approverId, $action, $comment) { - // 锁实例,保证并发安全 - $instance = Db::table('approval_instances')->where('id', $instanceId)->lockForUpdate()->first(); - if (!$instance) { - throw new BusinessException("审批实例未找到"); - } - if ($instance->status !== 'processing') { - throw new BusinessException("流程已结束或不可审批"); - } - - // 读取流程与当前步 - $flow = Db::table('approval_flows')->where('type', $instance->flow_type)->first(); - if (!$flow) throw new BusinessException("审批流程定义未找到"); - - $steps = json_decode($flow->steps, true); - $idx = (int)$instance->current_step; - $step = $steps[$idx] ?? null; - if (!$step) throw new BusinessException("当前步骤配置错误"); - - // 锁当前步所有记录,避免同时推进 - $pendingRecord = Db::table('approval_records') - ->where('instance_id', $instanceId) - ->where('approver_id', $approverId) - ->where('step_index', $idx) - ->where('status', 'pending') - ->lockForUpdate() - ->first(); - if (!$pendingRecord) { - throw new BusinessException("未找到待审批记录"); - } - - $now = date('Y-m-d H:i:s'); - - // 1) 更新当前人的审批记录 - Db::table('approval_records')->where('id', $pendingRecord->id)->update([ - 'action' => $action, - 'status' => ($action === 'approve') ? 'approved' : 'rejected', - 'comment' => $comment, - 'approved_at' => $now, - 'updated_at' => $now, - ]); - - // 2) 聚合判断本步骤结果 - $outcome = $this->getStepOutcome($instanceId, $idx); // 'pending'|'approve'|'reject' - $type = $step['type'] ?? 'all'; - - $stepDone = false; $finalReject = false; $finalApprove = false; - if ($type === 'any') { - if ($outcome === 'reject') { $stepDone = true; $finalReject = true; } - elseif ($outcome === 'approve') { $stepDone = true; $finalApprove = true; } - } else { // all - if ($outcome === 'reject') { $stepDone = true; $finalReject = true; } - elseif ($outcome === 'approve') { $stepDone = true; $finalApprove = true; } - } - - if (!$stepDone) { - return ['status' => 'step_pending']; - } - - // 3) 本步已有结论:关闭其余 pending 待办为 skipped - $this->closeOtherPending($instanceId, $idx, [$approverId]); - - // 4) 步骤结论为拒绝 -> 结束 - if ($finalReject) { - Db::table('approval_instances')->where('id', $instanceId)->update([ - 'status' => 'rejected', - 'finished_at' => $now, - 'updated_at' => $now, - ]); - $this->sendNotification([$instance->initiator_id], $instance, 'reject', false); - return ['status' => 'completed', 'result' => 'reject']; - } - - // 5) 进入下一步(基于表单快照与条件继续寻找) - $formData = json_decode($instance->form_data, true) ?: []; - $nextIndex = $this->getNextStepIndex($steps, $formData, $idx); - if ($nextIndex === null) { - // 流程结束(全通过) - Db::table('approval_instances')->where('id', $instanceId)->update([ - 'status' => 'approved', - 'finished_at' => $now, - 'updated_at' => $now, - ]); - $this->sendNotification([$instance->initiator_id], $instance, 'approve', false); - return ['status' => 'completed', 'result' => 'approve']; - } - - // 6) 推进实例 current_step(乐观条件) - $affected = Db::table('approval_instances') - ->where('id', $instanceId) - ->where('current_step', $idx) - ->where('status', 'processing') - ->update([ - 'current_step' => $nextIndex, - 'updated_at' => $now, - ]); - if (!$affected) { - throw new BusinessException('流程已被他人推进,请刷新后重试'); - } - - // 7) 生成下一步待办 + 通知 - $nextStep = $steps[$nextIndex]; - $nextApprovers = $this->resolveApprovers($nextStep, $instance, true); - foreach ($nextApprovers as $uid) { - $this->insertApprovalRecord($instanceId, $nextIndex, $uid); - } - $this->sendNotification($nextApprovers, $instance, 'pending', false); - $this->notifyCCs($nextStep, $instance, 'pending'); - - return ['status' => 'next_step', 'step_name' => $nextStep['name'] ?? ('Step '.$nextIndex)]; - }); - } - - /** - * 撤回流程(可选) - * 仅限发起人在第一条“已处理记录”出现前撤回 - */ - public function revoke(int $instanceId, int $initiatorId, string $reason = '') - { - return Db::transaction(function () use ($instanceId, $initiatorId, $reason) { - $instance = Db::table('approval_instances')->where('id', $instanceId)->lockForUpdate()->first(); - if (!$instance) throw new BusinessException('审批实例未找到'); - if ((int)$instance->initiator_id !== (int)$initiatorId) throw new BusinessException('无权撤回'); - - if ($instance->status !== 'processing') throw new BusinessException('流程已结束或不可撤回'); - - // 已有处理记录则不允许撤回 - $handled = Db::table('approval_records') - ->where('instance_id', $instanceId) - ->whereIn('status', ['approved','rejected','timeout','skipped']) - ->count() > 0; - if ($handled) throw new BusinessException('当前进度不可撤回'); - - $now = date('Y-m-d H:i:s'); - Db::table('approval_instances')->where('id', $instanceId)->update([ - 'status' => 'revoked', - 'finished_at' => $now, - 'updated_at' => $now, - ]); - - // 关闭所有 pending 待办 - Db::table('approval_records') - ->where('instance_id', $instanceId) - ->where('status', 'pending') - ->update(['status' => 'skipped', 'approved_at' => $now, 'updated_at' => $now]); - - $this->sendNotification([$initiatorId], $instance, 'revoked', false); - return ['status' => 'completed', 'result' => 'revoked']; - }); - } - - /** - * 我的待办 - */ - public function getPendingApprovals(int $userId): array - { - return Db::table('approval_records as ar') - ->join('approval_instances as ai', 'ar.instance_id', '=', 'ai.id') - ->where('ar.approver_id', $userId) - ->where('ar.status', 'pending') - ->where('ai.status', 'processing') - ->select('ai.*') - ->distinct() - ->get() - ->toArray(); - } - - /** - * 审批历史 - */ - public function getApprovalHistory(int $instanceId): array - { - return Db::table('approval_records') - ->where('instance_id', $instanceId) - ->orderBy('step_index') - ->orderByRaw('COALESCE(approved_at, created_at) asc') - ->get() - ->toArray(); - } - - /** - * 流程图数据(识别 skipped) - */ - public function getFlowDiagramData(int $instanceId): array - { - $instance = Db::table('approval_instances')->find($instanceId); - if (!$instance) return []; - - $flow = Db::table('approval_flows')->where('type', $instance->flow_type)->first(); - if (!$flow) return []; - - $steps = json_decode($flow->steps, true) ?: []; - $records = Db::table('approval_records') - ->where('instance_id', $instanceId) - ->orderBy('step_index')->orderByRaw('COALESCE(approved_at, created_at) asc') - ->get() - ->groupBy('step_index'); - - $formData = json_decode($instance->form_data, true) ?: []; - $data = []; - foreach ($steps as $i => $step) { - $actions = ($records->get($i) ?? collect())->toArray(); - - $status = 'pending'; - if (!empty($actions)) { - $hasReject = false; $allApproved = true; - foreach ($actions as $a) { - if ($a->status === 'rejected') $hasReject = true; - if ($a->status !== 'approved') $allApproved = false; - } - if ($hasReject) $status = 'rejected'; - elseif ($allApproved) $status = 'approved'; - else $status = 'processing'; - } else { - // 无记录:可能被跳过、未到达、已过 - if ($i < (int)$instance->current_step) { - // 如果条件不满足,认为 skipped,否则视为 approved(历史兼容) - if (isset($step['condition']) && !$this->evaluateCondition($step['condition'], $formData)) { - $status = 'skipped'; - } else { - $status = 'approved'; - } - } elseif ($i === (int)$instance->current_step && $instance->status === 'processing') { - $status = 'processing'; - } else { - // 还未到达 - $status = 'pending'; - } - } - - $data[] = [ - 'index' => $i, - 'name' => $step['name'] ?? ('Step '.$i), - 'type' => $step['type'] ?? 'all', - 'status' => $status, - 'actions' => $actions, - ]; - } - return $data; - } - - /** - * 定时任务:处理超时实例(实例级) - */ - public function handleTimeouts() - { - $now = date('Y-m-d H:i:s'); - $expired = Db::table('approval_instances') - ->where('status', 'processing') - ->whereNotNull('deadline_at') - ->where('deadline_at', '<=', $now) - ->get(); - - foreach ($expired as $instance) { - Db::transaction(function () use ($instance, $now) { - $flow = Db::table('approval_flows')->where('type', $instance->flow_type)->first(); - if (!$flow) return; - - $final = ($flow->timeout_action === 'auto_approve') ? 'approved' : 'rejected'; - $finalAction = ($flow->timeout_action === 'auto_approve') ? 'approve' : 'reject'; - - // 更新实例 - Db::table('approval_instances')->where('id', $instance->id)->update([ - 'status' => ($final === 'approved') ? 'approved' : 'rejected', - 'finished_at' => $now, - 'updated_at' => $now, - ]); - - // 关闭当前步所有 pending 记录为 timeout - Db::table('approval_records') - ->where('instance_id', $instance->id) - ->where('step_index', $instance->current_step) - ->where('status', 'pending') - ->update(['status' => 'timeout', 'approved_at' => $now, 'updated_at' => $now]); - - $this->notifyInitiator($instance, $finalAction); - }); - } - } - - // === 内部工具 === - - /** - * 解析审批人 - * $avoidSelf:是否过滤发起人本人 - */ - private function resolveApprovers(array $step, object $instance, bool $avoidSelf = true): array - { - $resolved = []; - $formData = json_decode($instance->form_data ?? '{}', true) ?: []; - - $confs = $step['approvers'] ?? []; - foreach ($confs as $cfg) { - $typ = $cfg['type'] ?? ''; - $val = $cfg['value'] ?? null; - $ids = []; - - switch ($typ) { - case 'role': - // $ids = $this->getUserIdsByRole($val); - - // 支持: - // - {"type":"role","value":1} // 按 role_id - // - {"type":"role","value":"销售经理"} // 按 roles.name - // - {"type":"role","value":"销售经理","system_id": 2} // 限定系统;默认也包含全局(system_id=0) - $val = $cfg['value'] ?? null; - $sys = isset($cfg['system_id']) ? (int)$cfg['system_id'] : null; - // include_global 默认 true(把 system_id=0 的“全局角色”也算上) - $includeGlobal = array_key_exists('include_global', $cfg) ? (bool)$cfg['include_global'] : true; - $ids = $this->getUserIdsByRole($val, $sys, true, $includeGlobal); - - break; - case 'user': - $ids = [(int)$val]; - break; - case 'initiator_leader': - $leaderId = $this->getLeaderIdByUserId((int)$instance->initiator_id); - if ($leaderId) $ids = [(int)$leaderId]; - break; - case 'field_user': - if (isset($formData[$val])) $ids = [(int)$formData[$val]]; - break; - case 'dept_head': - $head = $this->getDeptHeadId((int)$val); - if ($head) $ids = [(int)$head]; - break; - default: - throw new BusinessException("不支持的审批人类型: {$typ}"); - } - $resolved = array_merge($resolved, $ids); - } - - $resolved = array_unique(array_filter(array_map('intval', $resolved))); - if ($avoidSelf) { - $resolved = array_values(array_filter($resolved, fn($id) => $id !== (int)$instance->initiator_id)); - } - if (empty($resolved)) { - throw new BusinessException("步骤未解析到任何审批人"); - } - return $resolved; - } - - /** - * 通知抄送人 - */ - private function notifyCCs(array $step, object $instance, string $action = 'pending'): void - { - $ccConfig = $step['cc'] ?? []; - if (empty($ccConfig)) return; - - $formData = json_decode($instance->form_data ?? '{}', true) ?: []; - $uids = []; - - foreach ($ccConfig as $cc) { - $typ = $cc['type'] ?? ''; - $val = $cc['value'] ?? null; - - switch ($typ) { - case 'role': - $uids = array_merge($uids, $this->getUserIdsByRole($val)); - break; - case 'user': - $uids[] = (int)$val; - break; - case 'initiator_leader': - $leaderId = $this->getLeaderIdByUserId((int)$instance->initiator_id); - if ($leaderId) $uids[] = (int)$leaderId; - break; - case 'field_user': - if (isset($formData[$val])) $uids[] = (int)$formData[$val]; - break; - case 'dept_head': - $head = $this->getDeptHeadId((int)$val); - if ($head) $uids[] = (int)$head; - break; - default: - // ignore - break; - } - } - - $uids = array_unique(array_filter(array_map('intval', $uids))); - if (empty($uids)) return; - - $now = date('Y-m-d H:i:s'); - foreach ($uids as $uid) { - // 唯一键防重;这里仍做一次 exists 判断 - $exists = Db::table('approval_ccs') - ->where('instance_id', $instance->id) - ->where('user_id', $uid) - ->count() > 0; - if (!$exists) { - Db::table('approval_ccs')->insert([ - 'instance_id' => $instance->id, - 'user_id' => $uid, - 'notified_at' => $now, - 'created_at' => $now, - 'updated_at' => $now, - ]); - } - } - - $this->sendNotification($uids, $instance, $action, true); - } - - /** - * 条件求值:支持 {field} {op} {value} - * op: ==, !=, >, <, >=, <= - */ - private function evaluateCondition(?string $condition, array $formData): bool - { - if (!$condition) return true; - - $pattern = '/^(\w+)\s*(==|!=|>|<|>=|<=)\s*(.+)$/'; - if (!preg_match($pattern, $condition, $m)) { - throw new BusinessException("条件格式错误: {$condition}"); - } - - $field = $m[1]; - $op = $m[2]; - $value = trim($m[3], "\"'"); - - $actual = $formData[$field] ?? null; - - // 数值比较 - if (is_numeric($value) && is_numeric($actual)) { - $value = (float)$value; - $actual = (float)$actual; - } - - switch ($op) { - case '==': return $actual == $value; - case '!=': return $actual != $value; - case '>': return $actual > $value; - case '<': return $actual < $value; - case '>=': return $actual >= $value; - case '<=': return $actual <= $value; - } - throw new BusinessException("不支持的操作符: {$op}"); - } - - /** - * 获取下一个有效步骤索引(考虑 condition) - * @param int $currentStepIndex 从该索引之后开始找;如果传 -1 则从开头找“首个有效” - */ - private function getNextStepIndex(array $steps, array $formData, int $currentStepIndex): ?int - { - for ($i = $currentStepIndex + 1; $i < count($steps); $i++) { - $s = $steps[$i]; - if (!isset($s['condition']) || $this->evaluateCondition($s['condition'], $formData)) { - return $i; - } - } - return null; - } - - /** - * 聚合本步骤结论 - * 返回:'pending' | 'approve' | 'reject' - */ - private function getStepOutcome(int $instanceId, int $stepIndex): string - { - $records = Db::table('approval_records') - ->where('instance_id', $instanceId) - ->where('step_index', $stepIndex) - ->get(); - - $hasPending = false; $hasReject = false; $allApproved = true; - - foreach ($records as $r) { - if ($r->status === 'pending') { $hasPending = true; $allApproved = false; } - elseif ($r->status === 'rejected') { $hasReject = true; $allApproved = false; } - elseif ($r->status !== 'approved') { $allApproved = false; } - } - - if ($hasPending) return 'pending'; - if ($hasReject) return 'reject'; - return $allApproved ? 'approve' : 'reject'; - } - - /** - * 关闭本步其余待办(标记为 skipped) - */ - private function closeOtherPending(int $instanceId, int $stepIndex, array $keepApproverIds = []): void - { - $now = date('Y-m-d H:i:s'); - $q = Db::table('approval_records') - ->where('instance_id', $instanceId) - ->where('step_index', $stepIndex) - ->where('status', 'pending'); - - if (!empty($keepApproverIds)) { - $q->whereNotIn('approver_id', $keepApproverIds); - } - - $q->update([ - 'status' => 'skipped', - 'approved_at' => $now, - 'updated_at' => $now, - ]); - } - - private function insertApprovalRecord(int $instanceId, int $stepIndex, int $approverId): void - { - $now = date('Y-m-d H:i:s'); - - // 防重复:唯一键兜底,这里先查一次 - $exists = Db::table('approval_records') - ->where('instance_id', $instanceId) - ->where('step_index', $stepIndex) - ->where('approver_id', $approverId) - ->count() > 0; - - if (!$exists) { - Db::table('approval_records')->insert([ - 'instance_id' => $instanceId, - 'approver_id' => $approverId, - 'step_index' => $stepIndex, - 'action' => null, // 待办阶段无动作 - 'status' => 'pending', // 明确 pending - 'comment' => null, - 'approved_at' => null, // 未审批为 NULL - 'created_at' => $now, - 'updated_at' => $now, - ]); - } - } - - private function sendNotification(array $userIds, object $instance, string $action, bool $isCC): void - { - $map = [ - 'pending' => '待审批', - 'approve' => '已通过', - 'reject' => '已拒绝', - 'revoked' => '已撤回', - ]; - $prefix = $isCC ? '[抄送]' : ''; - $text = $map[$action] ?? $action; - $msg = "{$prefix}您有一条审批 {$text}:流程ID {$instance->id},类型 {$instance->flow_type}"; - // TODO: 接入你的消息系统(站内信/企微/飞书…) - // MessageService::send($userIds, $msg); - // echo "通知 ".implode(',', $userIds).":{$msg}\n"; - } - - private function notifyInitiator(object $instance, string $result): void - { - $this->sendNotification([(int)$instance->initiator_id], $instance, $result, false); - } - - // === 数据访问 === - - // private function getUserIdsByRole(string $roleCode): array - // { - // // 兼容 pluck 行为(不同版本可能返回 array 或 Collection) - // $rows = Db::table('user_roles as ur') - // ->join('roles as r', 'ur.role_id', '=', 'r.id') - // ->where('r.code', $roleCode) - // ->select('ur.user_id') - // ->get(); - - // $ids = []; - // foreach ($rows as $row) { - // $ids[] = (int)$row->user_id; - // } - // return array_values(array_unique($ids)); - // } - - /** - * 从角色取用户ID列表 - * - * @param mixed $roleIdOrName 数字 => role_id,字符串 => roles.name 精确匹配 - * @param int|null $systemId 可选:限定 roles.system_id;默认不传=不过滤 - * @param bool $onlyActive 是否仅取 status=1 的角色(默认 true) - * @param bool $includeGlobal 是否包含全局角色(system_id=0),默认 true - * @return int[] - */ - private function getUserIdsByRole($roleIdOrName, ?int $systemId = null, bool $onlyActive = true, bool $includeGlobal = true): array - { - // 查询构造 - // 情况A:纯数字 => 当作 role_id,优先直接走 user_roles(role_id) 索引 - if (is_int($roleIdOrName) || (is_string($roleIdOrName) && ctype_digit($roleIdOrName))) { - $roleId = (int)$roleIdOrName; - - // 如果不需要校验 roles 的 system/status,就不 join,性能更好 - $needJoin = $onlyActive || !is_null($systemId) || $includeGlobal === false; - - if (!$needJoin) { - $rows = Db::table('user_roles') - ->where('role_id', $roleId) - ->select('user_id') - ->get(); - } else { - $q = Db::table('user_roles as ur') - ->join('roles as r', 'ur.role_id', '=', 'r.id') - ->where('ur.role_id', $roleId) - ->select('ur.user_id'); - - if ($onlyActive) { - $q->where('r.status', 1); - } - if (!is_null($systemId)) { - if ($includeGlobal) { - $q->whereIn('r.system_id', [0, $systemId]); - } else { - $q->where('r.system_id', $systemId); - } - } - $rows = $q->get(); - } - } - // 情况B:字符串 => 当作 roles.name - else { - $name = (string)$roleIdOrName; - $q = Db::table('user_roles as ur') - ->join('roles as r', 'ur.role_id', '=', 'r.id') - ->where('r.name', $name) - ->select('ur.user_id'); - - if ($onlyActive) { - $q->where('r.status', 1); - } - if (!is_null($systemId)) { - if ($includeGlobal) { - $q->whereIn('r.system_id', [0, $systemId]); - } else { - $q->where('r.system_id', $systemId); - } - } - $rows = $q->get(); - } - - $ids = []; - foreach ($rows as $row) { - $ids[] = (int)$row->user_id; - } - return array_values(array_unique($ids)); - } - - - private function getLeaderIdByUserId(int $userId): ?int - { - $id = Db::table('user')->where('id', $userId)->value('report_to'); - return $id ? (int)$id : null; - } - - private function getDeptHeadId(int $deptId): ?int - { - $id = Db::table('departments')->where('id', $deptId)->value('head_user_id'); - return $id ? (int)$id : null; - } -} \ No newline at end of file diff --git a/app/common/utils/pdf/template/stockOrder.stub b/app/common/utils/pdf/template/stockOrder.stub index 6b93ecc..850f31f 100644 --- a/app/common/utils/pdf/template/stockOrder.stub +++ b/app/common/utils/pdf/template/stockOrder.stub @@ -240,15 +240,61 @@ -
| 阿里订单号/PI号: | +日期: | +关目的国: | +客户来源: | +客户名称: | +客户所在国: | +
| 编号 | +车型 | +数量/台 | +颜色/外 | +内饰 | +改装 | +单价 | +总价 | +官方指导价/二手挂牌价 | +优惠/二手减价 | +||
|---|---|---|---|---|---|---|---|---|---|---|---|
| + | + | + | + | + | + | + | + + 0): ?> + | + | + + | + | + + + |
| + 合同汇率: + | ++ 合计到岸价: + | +||||||||||
| 清关人: | +预计发运日期: | +出运方式: | +国内收货港: | +贸易条款/清关目的港: / | +最迟到港时间: | +
| 计划收款信息 | +序号 | +汇款国 | +日期 | +币种 | +账户 | +汇款人 | +金额 | +
|---|---|---|---|---|---|---|---|
| + | + | + | + | + | + | + |
diff --git a/app/common/utils/pdf/template/stockOrder_bak.stub b/app/common/utils/pdf/template/stockOrder_bak.stub new file mode 100644 index 0000000..6b93ecc --- /dev/null +++ b/app/common/utils/pdf/template/stockOrder_bak.stub @@ -0,0 +1,255 @@ + + +
+ +
+ + +
+