diff --git a/server-api/app/controller/admin/AppraisalTasksController.php b/server-api/app/controller/admin/AppraisalTasksController.php index 1c54a42..129bbdb 100644 --- a/server-api/app/controller/admin/AppraisalTasksController.php +++ b/server-api/app/controller/admin/AppraisalTasksController.php @@ -2150,6 +2150,8 @@ class AppraisalTasksController $verify = $this->createOrUpdateVerifyRecord($report, $now); if (($report['report_type'] ?? 'appraisal') === 'appraisal' && (int)($report['order_id'] ?? 0) > 0) { + (new MaterialTagService())->syncBoundTagForReport($report, $request); + Db::name('orders')->where('id', (int)$report['order_id'])->update([ 'order_status' => 'report_published', 'display_status' => '报告已出具', diff --git a/server-api/app/controller/admin/ReportsController.php b/server-api/app/controller/admin/ReportsController.php index 5474092..00a0aea 100644 --- a/server-api/app/controller/admin/ReportsController.php +++ b/server-api/app/controller/admin/ReportsController.php @@ -435,8 +435,10 @@ class ReportsController $effectivePublishTime = $report['publish_time'] ?: $now; $isOrderAppraisalReport = ($report['report_type'] ?? 'appraisal') === 'appraisal' && (int)($report['order_id'] ?? 0) > 0; $materialTag = null; + $materialTagService = new MaterialTagService(); if ($isOrderAppraisalReport) { - $materialTag = (new MaterialTagService())->findBoundTagForReport($id); + $materialTag = $materialTagService->findBoundTagForReport($id) + ?: $materialTagService->syncBoundTagForReport($report, $request); if (!$materialTag) { if ($qrInput === '') { Db::rollback(); @@ -452,7 +454,7 @@ class ReportsController return api_error('报告未关联鉴定任务,不能绑定吊牌发布', 422); } - $materialTag = (new MaterialTagService())->bindTagToReportByTask((int)$task['id'], $qrInput, $request); + $materialTag = $materialTagService->bindTagToReportByTask((int)$task['id'], $qrInput, $request); } } @@ -476,6 +478,7 @@ class ReportsController if ($isOrderAppraisalReport) { $this->refreshAppraisalSnapshot((int)$report['id'], (int)$report['order_id'], $report['service_provider'], $now); + $materialTag = $materialTagService->syncBoundTagForReport($report, $request) ?: $materialTag; } $verify = $this->createOrUpdateVerifyRecord($report, $now); diff --git a/server-api/app/support/MaterialTagService.php b/server-api/app/support/MaterialTagService.php index 76f7a3d..02b72ec 100644 --- a/server-api/app/support/MaterialTagService.php +++ b/server-api/app/support/MaterialTagService.php @@ -484,6 +484,102 @@ class MaterialTagService return $this->formatTagCode($tag, $report ?: null); } + public function syncBoundTagForReport(array $report, ?Request $request = null): ?array + { + $reportId = (int)($report['id'] ?? 0); + $orderId = (int)($report['order_id'] ?? 0); + $reportNo = trim((string)($report['report_no'] ?? '')); + if ($reportId <= 0 || $orderId <= 0 || $reportNo === '' || ($report['report_type'] ?? 'appraisal') !== 'appraisal') { + return null; + } + + $tag = Db::name('material_tag_codes')->where('report_id', $reportId)->find(); + if (!$tag) { + $tag = Db::name('material_tag_codes') + ->where('bound_order_id', $orderId) + ->where('bind_status', 'bound') + ->where('status', '<>', 'invalid') + ->order('bound_at', 'desc') + ->order('id', 'desc') + ->find(); + } + if (!$tag && $reportNo !== '') { + $tag = Db::name('material_tag_codes') + ->where('report_no', $reportNo) + ->where('bind_status', 'bound') + ->where('status', '<>', 'invalid') + ->order('id', 'desc') + ->find(); + } + if (!$tag) { + return null; + } + + $batch = Db::name('material_batches')->where('id', (int)$tag['batch_id'])->find(); + if (($tag['status'] ?? 'active') === 'invalid' || ($batch && ($batch['status'] ?? 'active') === 'invalid')) { + return null; + } + + $now = date('Y-m-d H:i:s'); + $payload = [ + 'report_id' => $reportId, + 'report_no' => $reportNo, + 'bind_status' => 'bound', + 'bound_order_id' => $orderId, + 'updated_at' => $now, + ]; + if (empty($tag['bound_by'])) { + $payload['bound_by'] = $request ? ((int)$request->header('x-admin-id', 0) ?: null) : null; + } + if (trim((string)($tag['bound_by_name'] ?? '')) === '') { + $payload['bound_by_name'] = $request ? trim((string)$request->header('x-admin-name', '')) : ''; + } + if (empty($tag['bound_at'])) { + $payload['bound_at'] = $now; + } + + Db::name('material_tag_codes')->where('id', (int)$tag['id'])->update($payload); + $fresh = Db::name('material_tag_codes')->where('id', (int)$tag['id'])->find(); + return $this->formatTagCode($fresh ?: array_merge($tag, $payload), $report); + } + + private function findPublishedReportForTag(array $tag): ?array + { + if ((int)($tag['report_id'] ?? 0) > 0) { + $report = Db::name('reports') + ->where('id', (int)$tag['report_id']) + ->where('report_status', 'published') + ->find(); + if ($report) { + return $report; + } + } + + $reportNo = trim((string)($tag['report_no'] ?? '')); + if ($reportNo !== '') { + $report = Db::name('reports') + ->where('report_no', $reportNo) + ->where('report_status', 'published') + ->find(); + if ($report) { + return $report; + } + } + + $orderId = (int)($tag['bound_order_id'] ?? 0); + if ($orderId <= 0) { + return null; + } + + return Db::name('reports') + ->where('order_id', $orderId) + ->where('report_type', 'appraisal') + ->where('report_status', 'published') + ->order('publish_time', 'desc') + ->order('id', 'desc') + ->find() ?: null; + } + public function showPublicTag(string $token, Request $request): array { $tag = Db::name('material_tag_codes')->where('qr_token', $token)->find(); @@ -521,6 +617,14 @@ class MaterialTagService $report = (int)($tag['report_id'] ?? 0) > 0 ? Db::name('reports')->where('id', (int)$tag['report_id'])->find() : null; + $publishedReport = $this->findPublishedReportForTag($tag); + if ($publishedReport && (!$report || ($report['report_status'] ?? '') !== 'published' || (int)$report['id'] !== (int)$publishedReport['id'])) { + $this->syncBoundTagForReport($publishedReport, $request); + $tag = Db::name('material_tag_codes')->where('id', (int)$tag['id'])->find() ?: $tag; + $tag['scan_count'] = max((int)$tag['scan_count'], 1); + $tag['last_scanned_at'] = $now; + $report = $publishedReport; + } if (!$report) { return [ @@ -597,6 +701,12 @@ class MaterialTagService $report = (int)($tag['report_id'] ?? 0) > 0 ? Db::name('reports')->where('id', (int)$tag['report_id'])->find() : null; + $publishedReport = $this->findPublishedReportForTag($tag); + if ($publishedReport && (!$report || ($report['report_status'] ?? '') !== 'published' || (int)$report['id'] !== (int)$publishedReport['id'])) { + $this->syncBoundTagForReport($publishedReport, $request); + $tag = Db::name('material_tag_codes')->where('id', (int)$tag['id'])->find() ?: $tag; + $report = $publishedReport; + } $passed = $report && ($report['report_status'] ?? '') === 'published' @@ -963,8 +1073,7 @@ class MaterialTagService $tag = Db::name('material_tag_codes')->where('qr_token', $token)->find(); if ( !$tag - || (int)($tag['report_id'] ?? 0) <= 0 - || ($tag['bind_status'] ?? '') !== 'bound' + || ((int)($tag['report_id'] ?? 0) <= 0 && (int)($tag['bound_order_id'] ?? 0) <= 0 && trim((string)($tag['report_no'] ?? '')) === '') || ($tag['status'] ?? 'active') === 'invalid' ) { return ''; @@ -975,10 +1084,10 @@ class MaterialTagService return ''; } - $report = Db::name('reports') - ->where('id', (int)$tag['report_id']) - ->where('report_status', 'published') - ->find(); + $report = $this->findPublishedReportForTag($tag); + if ($report) { + $this->syncBoundTagForReport($report); + } return $report ? (string)$report['report_no'] : ''; }