diff --git a/app/Http/Controllers/Business/Pages.php b/app/Http/Controllers/Business/Pages.php index 7c4ff714..6e62f11e 100644 --- a/app/Http/Controllers/Business/Pages.php +++ b/app/Http/Controllers/Business/Pages.php @@ -329,8 +329,22 @@ class Pages extends Controller protected function contentForDingPayableWorkflows(): array { + $normalizeDate = static function (mixed $value): string { + $date = trim((string) $value); + if (preg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $date, $matches) !== 1 + || ! checkdate((int) $matches[2], (int) $matches[3], (int) $matches[1])) { + return ''; + } + + return $date; + }; + $status = strtoupper(mb_substr(trim((string) request('status', '')), 0, 30)); + $filters = [ 'process_instance_id' => mb_substr(trim((string) request('process_instance_id', '')), 0, 100), + 'created_from' => $normalizeDate(request('created_from', '')), + 'finished_to' => $normalizeDate(request('finished_to', '')), + 'status' => preg_match('/^[A-Z_]+$/', $status) === 1 ? $status : '', ]; $page = max((int) request('page', 1), 1); $limit = min(max((int) setting('default.list_limit', 25), 1), 100); diff --git a/modules/EcommerceFinance/Repositories/DingPayableWorkflowMirrorRepository.php b/modules/EcommerceFinance/Repositories/DingPayableWorkflowMirrorRepository.php index 48a72cb0..14cc79f8 100644 --- a/modules/EcommerceFinance/Repositories/DingPayableWorkflowMirrorRepository.php +++ b/modules/EcommerceFinance/Repositories/DingPayableWorkflowMirrorRepository.php @@ -63,6 +63,9 @@ class DingPayableWorkflowMirrorRepository && ! str_contains((string) ($workflow['businessId'] ?? ''), (string) $filters['process_instance_id'])) { continue; } + if (! $this->matchesWorkflowFilters($workflow, $filters)) { + continue; + } $scheme = $this->decode((string) $record->scheme_payload, []); $forms = $this->formFields($scheme); @@ -94,6 +97,46 @@ class DingPayableWorkflowMirrorRepository ]; } + /** @param array $workflow @param array $filters */ + private function matchesWorkflowFilters(array $workflow, array $filters): bool + { + $createdFrom = trim((string) ($filters['created_from'] ?? '')); + if ($createdFrom !== '') { + $createdAt = $this->workflowDate($workflow['createAt'] ?? null); + if ($createdAt === null || $createdAt < $createdFrom) { + return false; + } + } + + $finishedTo = trim((string) ($filters['finished_to'] ?? '')); + if ($finishedTo !== '') { + $finishTime = $this->workflowDate($workflow['finishTime'] ?? null); + if ($finishTime === null || $finishTime > $finishedTo) { + return false; + } + } + + $requestedStatus = strtoupper(trim((string) ($filters['status'] ?? ''))); + if ($requestedStatus !== '') { + $actualStatus = strtoupper(trim((string) ($workflow['status'] ?? ''))); + $statusMatches = $requestedStatus === 'CANCELED' + ? in_array($actualStatus, ['CANCELED', 'CANCELLED'], true) + : $actualStatus === $requestedStatus; + if (! $statusMatches) { + return false; + } + } + + return true; + } + + private function workflowDate(mixed $value): ?string + { + $date = substr(trim((string) ($value ?? '')), 0, 10); + + return preg_match('/^\d{4}-\d{2}-\d{2}$/', $date) === 1 ? $date : null; + } + /** @return array */ private function formFields(array $rows): array { diff --git a/resources/views/business/pages/courier-payables/payable-cloud-warehouse-vehicle-fee.blade.php b/resources/views/business/pages/courier-payables/payable-cloud-warehouse-vehicle-fee.blade.php index b1317db5..84023919 100644 --- a/resources/views/business/pages/courier-payables/payable-cloud-warehouse-vehicle-fee.blade.php +++ b/resources/views/business/pages/courier-payables/payable-cloud-warehouse-vehicle-fee.blade.php @@ -32,6 +32,15 @@ 'DELETED' => '已删除', ][strtoupper($status)] ?? $status; }; + $statusOptions = [ + '' => '全部状态', + 'RUNNING' => '进行中', + 'COMPLETED' => '已完成', + 'TERMINATED' => '已终止', + 'CANCELED' => '已取消', + 'REJECTED' => '已驳回', + 'FAILED' => '失败', + ]; @endphp
@@ -40,8 +49,11 @@ .ding-payable-toolbar { display:flex; flex-wrap:wrap; align-items:flex-end; gap:.75rem; padding:1rem; margin-bottom:1rem; border:1px solid var(--vip-border,#D8D2C7); border-radius:.5rem; background:var(--vip-surface,#fff); } .ding-payable-field { display:flex; flex-direction:column; gap:.35rem; min-width:16rem; } .ding-payable-field label { color:var(--vip-content-muted,#595959); font-size:.75rem; font-weight:600; } - .ding-payable-field input { height:2.25rem; padding:0 .65rem; border:1px solid var(--vip-border,#D8D2C7); border-radius:.5rem; background:#fff; color:var(--vip-content-ink,#171717); } - .ding-payable-field input:focus { border-color:var(--vip-content-accent-dark,#856632); outline:none; box-shadow:0 0 0 3px rgba(133,102,50,.2); } + .ding-payable-field input,.ding-payable-field select { height:2.25rem; padding:0 .65rem; border:1px solid var(--vip-border,#D8D2C7); border-radius:.5rem; background:#fff; color:var(--vip-content-ink,#171717); } + .ding-payable-field input:focus,.ding-payable-field select:focus { border-color:var(--vip-content-accent-dark,#856632); outline:none; box-shadow:0 0 0 3px rgba(133,102,50,.2); } + .ding-payable-date-range { display:flex; align-items:center; gap:.5rem; } + .ding-payable-date-range input { min-width:9rem; } + .ding-payable-date-range span { color:var(--vip-content-muted,#595959); } .ding-payable-actions { display:flex; gap:.5rem; } .ding-payable-button { display:inline-flex; align-items:center; gap:.35rem; height:2.25rem; padding:0 .85rem; border:1px solid var(--vip-border,#D8D2C7); border-radius:.5rem; background:#fff; color:var(--vip-content-ink,#171717); text-decoration:none; font-weight:600; } .ding-payable-button.primary { border-color:var(--vip-content-accent-dark,#856632); background:var(--vip-content-accent-dark,#856632); color:#fff; } @@ -66,6 +78,22 @@
+
+ +
+ + + +
+
+
+ + +
重置 diff --git a/tests/Feature/Business/DingPayableWorkflowPageTest.php b/tests/Feature/Business/DingPayableWorkflowPageTest.php index f9091d0f..97660372 100644 --- a/tests/Feature/Business/DingPayableWorkflowPageTest.php +++ b/tests/Feature/Business/DingPayableWorkflowPageTest.php @@ -66,4 +66,39 @@ class DingPayableWorkflowPageTest extends FeatureTestCase ->assertSee('钉钉应付流程镜像尚未完成同步,请稍后重试。') ->assertSee('镜像读取失败,请稍后重试。'); } + + public function test_cloud_warehouse_vehicle_fee_page_passes_workflow_time_and_status_filters(): void + { + $this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail()); + $repository = Mockery::mock(DingPayableWorkflowMirrorRepository::class); + $repository->shouldReceive('paginate')->once()->with( + [ + 'process_instance_id' => '', + 'created_from' => '2026-07-01', + 'finished_to' => '2026-07-31', + 'status' => 'COMPLETED', + ], + 1, + Mockery::type('int'), + )->andReturn([ + 'data' => [], + 'total' => 0, + 'status' => 'succeeded', + 'last_synced_at' => '2026-08-29 10:11:24', + ]); + $this->app->instance(DingPayableWorkflowMirrorRepository::class, $repository); + + $this->loginAs()->get(route('business.pages.show', [ + 'section' => 'courier-payables', + 'page' => 'payable-cloud-warehouse-vehicle-fee', + 'created_from' => '2026-07-01', + 'finished_to' => '2026-07-31', + 'status' => 'completed', + ]))->assertOk() + ->assertSee('流程时间(创建时间至完成时间)') + ->assertSee('2026-07-01') + ->assertSee('2026-07-31') + ->assertSee('状态') + ->assertSee('全部状态'); + } }