diff --git a/resources/views/business/pages/courier-payables/agreement-signing.blade.php b/resources/views/business/pages/courier-payables/agreement-signing.blade.php index 61a7e6d5..d5b52c6a 100644 --- a/resources/views/business/pages/courier-payables/agreement-signing.blade.php +++ b/resources/views/business/pages/courier-payables/agreement-signing.blade.php @@ -1153,7 +1153,8 @@ .agreement-preview-signature { margin-top: 2.5rem; - text-align: right; + padding: 0; + text-align: left; } .agreement-preview-signature--split { @@ -1163,6 +1164,9 @@ text-align: left; } + .agreement-preview-signature-slot { padding: 0.75rem; } + .agreement-preview-signature-blank { height: 15rem; } + .agreement-preview-handwriting-blank { height: 6.25rem; } .agreement-preview-list { margin: 0.75rem 0; padding-left: 1.4rem; @@ -1872,6 +1876,7 @@

以上收款账户的变更,以我司的盖章为有效。

待填写:

+

日期:{{ now()->format('Y年n月j日') }}

第 1 页 / 共 1 页

@@ -1890,6 +1895,7 @@

以上收款账户的变更,以我司的盖章为有效。

待填写:

+

日期:{{ now()->format('Y年n月j日') }}

第 1 页 / 共 1 页

@@ -1902,11 +1908,25 @@

变更后,原公司的各项事宜由变更后的公司继续执行。原公司的结算未付款项,由变更之后的公司提供的收款账户收款。原公司的业务和款项若出现法律上的纠纷,由变更后的公司承担责任。

特此证明!

-
-

变更前公司法人签字盖公章:

- -

变更后公司法人签字盖公章:待填写(签署人:待填写)

-

日期:{{ now()->format('Y年n月j日') }}

+
+
+

变更前公司法人签字盖公章:待填写

+

签署人:待填写

+ +
+
+

法人签字:

+
+
+

日期:{{ now()->format('Y年n月j日') }}

+
+
+

变更后公司法人签字盖公章:待填写(签署人:待填写)

+
+

法人签字:

+
+

日期:{{ now()->format('Y年n月j日') }}

+

第 1 页 / 共 1 页

@@ -1919,6 +1939,7 @@

确认企业:待填写

法人签字并公司盖章:

+

日期:{{ now()->format('Y年n月j日') }}

第 1 页 / 共 1 页

@@ -1947,11 +1968,20 @@

委托代签以上事项时效性,以委托书上签的有效期为准,委托有效期:从 待填写 至 待填写 止。

-

委托方:待填写

-

受托方:待填写

-
-
-

日期:{{ now()->format('Y年n月j日') }}

+
+

委托方:待填写

+
+

签字:

+
+

日期:{{ now()->format('Y年n月j日') }}

+
+
+

受托方:待填写

+
+

签字:

+
+

日期:{{ now()->format('Y年n月j日') }}

+

第 1 页 / 共 1 页

@@ -1971,7 +2001,7 @@

双方确认以下报价版本作为快递服务结算依据。报价版本一经签署即形成独立留档,后续变价须生成新版本并重新签署。

请选择报价版本后查看报价明细
-

乙方(快递方)签章:

日期:{{ now()->format('Y年n月j日') }}

+

乙方(快递方)签章:

日期:{{ now()->format('Y年n月j日') }}

报价确认单 · 快递方单方签署

diff --git a/resources/views/business/partials/cooperation-contract.blade.php b/resources/views/business/partials/cooperation-contract.blade.php index 78f69095..b305784f 100644 --- a/resources/views/business/partials/cooperation-contract.blade.php +++ b/resources/views/business/partials/cooperation-contract.blade.php @@ -124,14 +124,45 @@ @if ($preview)
-

甲 方:待填写

-

乙 方:待填写

-

代表人:

-

代表人:

-

日 期:待填写

-

日 期:待填写

-

签约地:常州市

+
+

甲 方:待填写

+
+

代表人:

+
+

日 期:待填写

+

签约地:常州市

+
+
+

乙 方:待填写

+
+

代表人:

+
+

日 期:待填写

+

签约地:常州市

+
@else -

甲 方:{!! $mixedText($payload['cooperation_party_a_name'] ?? '') !!}

乙 方:{!! $mixedText($payload['cooperation_party_b_name'] ?? '') !!}

代表人:

代表人:

日 期:{!! $mixedText($signatureDate) !!}

日 期:{!! $mixedText($signatureDate) !!}

签约地:常州市

+
+

签署及盖章

+ + + + + +
+

甲 方:{!! $mixedText($payload['cooperation_party_a_name'] ?? '') !!}

+
+

代表人:

+
+

日 期:{!! $mixedText($signatureDate) !!}

+

签约地:常州市

+
+

乙 方:{!! $mixedText($payload['cooperation_party_b_name'] ?? '') !!}

+
+

代表人:

+
+

日 期:{!! $mixedText($signatureDate) !!}

+

签约地:常州市

+
+
@endif diff --git a/resources/views/business/pdf/courier-agreement.blade.php b/resources/views/business/pdf/courier-agreement.blade.php index 7d701f9d..eb13d695 100644 --- a/resources/views/business/pdf/courier-agreement.blade.php +++ b/resources/views/business/pdf/courier-agreement.blade.php @@ -14,12 +14,28 @@ .meta { color: #595959; font-size: 11px; text-align: right; margin-bottom: 20px; } .account { margin: 14px 0 20px 28px; } .account div { margin: 6px 0; } - .sign { margin-top: 36px; text-align: right; page-break-inside: avoid; } - .sign p { margin: 8px 0; } .authorization-list { margin: 0 0 12px; } .authorization-item { display: table; width: 100%; padding-bottom: 4px; } .authorization-item__number { display: table-cell; width: 24px; padding-right: 4px; vertical-align: top; white-space: nowrap; } .authorization-item__text { display: table-cell; vertical-align: top; } + .sign { margin: 36px 0 0 auto; padding: 0; page-break-inside: avoid; text-align: left; } + .sign p { margin: 10px 0; min-height: 24px; } + .sign--single { width: 68%; } + .sign--split { width: 100%; margin-top: 30px; padding: 0; border: 0; } + .sign-grid { width: 100%; table-layout: fixed; border-collapse: separate; border-spacing: 14px 0; } + .sign-grid td { padding: 16px; vertical-align: top; } + .sign-grid__title { margin: 0 0 12px; font-weight: 700; } + .sign-grid__blank { height: 240px; } + .sign-grid__handwriting { height: 100px; } + .sign-grid__line { margin: 0 0 10px; min-height: 24px; } + .contract-signatures { page-break-before: always; margin-top: 0; padding-top: 12px; } + .contract-signatures__heading { margin: 0 0 16px; font-size: 14px; } + .contract-signatures__table { width: 100%; table-layout: fixed; border-collapse: separate; border-spacing: 14px 0; } + .contract-signatures__table td { padding: 18px; vertical-align: top; } + .contract-signatures__title { margin: 0 0 12px; font-weight: 700; } + .contract-signatures__blank { height: 240px; } + .contract-signatures__handwriting { height: 100px; } + .contract-signatures__line { margin: 0 0 10px; min-height: 24px; } .page { page-break-after: always; } .cooperation-parties { margin: 14px 0 20px; } .cooperation-parties div { margin: 6px 0; } @@ -60,7 +76,7 @@

请贵公司按照上述汇款资料付款,如因我司提供收款银行帐户资料错误,导致相关款项支付不到位,则由此产生的一切经济纠纷和责任由我司承担。我司承诺若上述收款银行帐户资料发生变化及时书面通知贵公司。

以上收款账户的变更,以我司的盖章为有效。

-

公司盖章:

日期:{!! $mixedText($signatureDate) !!}

+

公司盖章:

日期:{!! $mixedText($signatureDate) !!}

@elseif ($type === 'account-change')

TO {!! $mixedText($payload['company_full_name']) !!}:

基于我公司正规化管理的需要,同时保证广大客户的汇款安全,我司收款账户将于 {!! $mixedText($payload['account_change_date']) !!} 变更账户,之前相应的账户(收款账户为:{!! $mixedText($payload['old_account_name']) !!},账号:{!! $mixedText($payload['old_account_number']) !!})于 {!! $mixedText($payload['old_account_stop_date']) !!} 停止使用,即日起我司收款的银行帐户进行变更,自 {!! $mixedText($payload['new_account_effective_date']) !!} 起我司与贵司往来款项请汇款至以下新账户,新汇款资料如下:

@@ -70,7 +86,7 @@
银行账户:{!! $mixedText($payload['new_bank_account']) !!}

如因我司提供收款银行帐户资料错误导致相关款项支付不到位,由此产生的一切经济纠纷和责任由我司承担。以上收款账户的变更,以我司的盖章为有效。

-

公司盖章:

日期:{!! $mixedText($signatureDate) !!}

+

公司盖章:

日期:{!! $mixedText($signatureDate) !!}

@elseif ($type === 'entity-change')

致 {!! $mixedText($payload['company_full_name']) !!}:

@if (filter_var($payload['entity_change_old_company_deregistered'] ?? false, FILTER_VALIDATE_BOOLEAN)) @@ -80,14 +96,35 @@ @endif

变更后,原公司的各项事宜由变更后的公司继续执行。原公司的结算未付款项,由变更之后的公司提供的收款账户收款。原公司的业务和款项若出现法律上的纠纷,由变更后的公司承担责任。

特此证明!

-
- @if (filter_var($payload['entity_change_old_company_deregistered'] ?? false, FILTER_VALIDATE_BOOLEAN)) -

原公司法人个人签字:{!! $mixedText($payload['former_legal_representative'] ?? '') !!}

- @else -

变更前公司法人签字盖公章:{!! $mixedText($payload['former_company_name']) !!}(签署人:{!! $mixedText($payload['former_legal_representative'] ?? '') !!})

- @endif -

变更后公司法人签字盖公章:{!! $mixedText($payload['changed_company_name']) !!}(签署人:{!! $mixedText($payload['secondary_operator_name'] ?? '') !!})

-

日期:{!! $mixedText($signatureDate) !!}

+
+ + + + + +
+

变更前主体

+ @if (filter_var($payload['entity_change_old_company_deregistered'] ?? false, FILTER_VALIDATE_BOOLEAN)) +

原公司法人个人签字:{!! $mixedText($payload['former_legal_representative'] ?? '') !!}

+ @else +

变更前公司法人签字盖公章:{!! $mixedText($payload['former_company_name']) !!}

+

签署人:{!! $mixedText($payload['former_legal_representative'] ?? '') !!}

+ @endif +
+ @if (! filter_var($payload['entity_change_old_company_deregistered'] ?? false, FILTER_VALIDATE_BOOLEAN)) +

法人签字:

+
+ @endif +

日期:{!! $mixedText($signatureDate) !!}

+
+

变更后主体

+

变更后公司法人签字盖公章:{!! $mixedText($payload['changed_company_name']) !!}

+

签署人:{!! $mixedText($payload['secondary_operator_name'] ?? '') !!}

+
+

法人签字:

+
+

日期:{!! $mixedText($signatureDate) !!}

+
@elseif ($type === 'shared-contract')

与 {!! $mixedText($payload['company_full_name'] ?? $signature->company_full_name) !!} 合作的 {!! $mixedText($sharedCourierText) !!},均归属于 {!! $mixedText($payload['contract_partner_name'] ?? '') !!},共用一份合同及同一份打款资料,合同签署及结算主体均为 {!! $mixedText($payload['contract_partner_name'] ?? '') !!}。

@@ -95,13 +132,14 @@ @if (filled($payload['shared_note'] ?? null))

备注:{!! $mixedText($payload['shared_note']) !!}

@endif -
+
@if (($payload['counterparty_signer_type'] ?? 'organization') === 'person')

确认人(个人签字):{!! $mixedText($payload['contract_partner_name'] ?? '') !!}

@else

确认企业:{!! $mixedText($payload['contract_partner_name'] ?? '') !!}

法人签字并公司盖章:

@endif +

日期:{!! $mixedText($signatureDate) !!}

@elseif ($type === 'cooperation-contract') @@ -121,7 +159,14 @@
4.代表委托方代收 {!! $mixedText($payload['payment_counterparty']) !!} 的往来货款。

委托有效期:从 {!! $mixedText($payload['authorization_start_date']) !!} 至 {!! $mixedText($payload['authorization_end_date']) !!} 止。

-

委托方:{!! $mixedText($payload['principal_name']) !!}

受托方:{!! $mixedText($payload['trustee_name']) !!}

日期:{!! $mixedText($signatureDate) !!}

+
+ + + + + +

委托方

{!! $mixedText($payload['principal_name']) !!}

签字:

日期:{!! $mixedText($signatureDate) !!}

受托方

{!! $mixedText($payload['trustee_name']) !!}

签字:

日期:{!! $mixedText($signatureDate) !!}

+
@endif diff --git a/resources/views/business/pdf/courier-quote.blade.php b/resources/views/business/pdf/courier-quote.blade.php index f2bd000e..9837f254 100644 --- a/resources/views/business/pdf/courier-quote.blade.php +++ b/resources/views/business/pdf/courier-quote.blade.php @@ -35,7 +35,8 @@ .signature { page-break-before: always; } .signature h2 { margin-top: 0; } .signature__meta { margin-bottom: 18px; color: #555; } - .signature__box { width: 250px; height: 82px; margin-left: auto; border: 1px solid #777; padding: 8px; color: #666; } + .signature__box { width: 360px; margin-left: auto; padding: 14px 16px; color: #666; page-break-inside: avoid; } + .signature__blank { height: 240px; } .document-control { margin-top: 22px; border-top: 1px solid #bbb; padding-top: 6px; color: #777; font-size: 7.5px; text-align: right; } @@ -134,7 +135,7 @@

签署确认

报价版本:{!! $mixedText($version->version_code) !!} 快递公司:{!! $mixedText($version->carrier_name) !!} 执行日期:{!! $mixedText($version->effective_date?->toDateString()) !!}
-
乙方(快递方)签章:{!! $mixedText($version->carrier_name) !!}

签署日期:{!! $mixedText($signatureDate) !!}
+
乙方(快递方)签章:{!! $mixedText($version->carrier_name) !!}
签署日期:{!! $mixedText($signatureDate) !!}
生成时间:{!! $mixedText($generatedAt->format('Y-m-d H:i:s')) !!} · 版本 {!! $mixedText($version->version_code) !!}
diff --git a/tests/Feature/Business/CourierAgreementSignatureWorkflowTest.php b/tests/Feature/Business/CourierAgreementSignatureWorkflowTest.php index aecc05c1..e906b06a 100644 --- a/tests/Feature/Business/CourierAgreementSignatureWorkflowTest.php +++ b/tests/Feature/Business/CourierAgreementSignatureWorkflowTest.php @@ -267,7 +267,8 @@ class CourierAgreementSignatureWorkflowTest extends FeatureTestCase 'fontPath' => str_replace('\\', '/', resource_path('fonts/DroidSansFallback.ttf')), ])->render(); $this->assertStringContainsString('原公司法人个人签字:原法人', strip_tags($html)); - $this->assertStringContainsString('变更后公司法人签字盖公章:新公司有限公司(签署人:新法人)', strip_tags($html)); + $this->assertStringContainsString('变更后公司法人签字盖公章:新公司有限公司', strip_tags($html)); + $this->assertStringContainsString('签署人:新法人', strip_tags($html)); $this->assertStringNotContainsString('变更前公司法人签字盖公章', $html); Http::assertSent(function (ClientRequest $request): bool { diff --git a/tests/Unit/CourierAgreementSignatureLayoutTest.php b/tests/Unit/CourierAgreementSignatureLayoutTest.php new file mode 100644 index 00000000..2face374 --- /dev/null +++ b/tests/Unit/CourierAgreementSignatureLayoutTest.php @@ -0,0 +1,107 @@ +renderLayout('cooperation-contract'); + $seals = array_values(array_filter($frames, fn ($frame) => $frame['class'] === 'contract-signatures__blank')); + $handwriting = array_values(array_filter($frames, fn ($frame) => $frame['class'] === 'contract-signatures__handwriting')); + + $this->assertCount(2, $seals); + $this->assertCount(2, $handwriting); + $this->assertGreaterThan(1, $pageCount); + foreach ($seals as $index => $seal) { + $this->assertGreaterThanOrEqual(159, $seal['width']); + $this->assertGreaterThanOrEqual(159, $seal['height']); + $this->assertSame($pageCount, $seal['page']); + $this->assertGreaterThanOrEqual(75, $handwriting[$index]['height']); + $this->assertGreaterThanOrEqual($seal['y'] + $seal['height'], $handwriting[$index]['y']); + } + $this->assertLessThanOrEqual($seals[1]['x'], $seals[0]['x'] + $seals[0]['width']); + foreach ($frames as $frame) { + $this->assertSame($pageCount, $frame['page'], 'Both parties and their dates must stay on the signature page.'); + $this->assertLessThan(806, $frame['y'] + $frame['height']); + } + } + + public function test_other_agreements_keep_full_size_seal_spaces_and_dates_together(): void + { + foreach (['account-proof', 'account-change', 'entity-change', 'shared-contract', 'authorization'] as $type) { + [$frames, $pageCount] = $this->renderLayout($type); + $seals = array_values(array_filter($frames, fn ($frame) => $frame['class'] === 'sign-grid__blank')); + $this->assertCount(in_array($type, ['entity-change', 'authorization'], true) ? 2 : 1, $seals); + foreach ($seals as $seal) { + $this->assertGreaterThanOrEqual(159, $seal['width'], $type); + $this->assertGreaterThanOrEqual(159, $seal['height'], $type); + } + foreach ($frames as $frame) { + $this->assertSame($pageCount, $frame['page'], "$type signature spaces and dates must stay together."); + $this->assertLessThan(806, $frame['y'] + $frame['height'], $type); + } + } + } + + private function renderLayout(string $type): array + { + $payload = [ + 'company_full_name' => '示例甲方公司', 'signature_date' => '2026-10-11', + 'account_proof_effective_date' => '2026-10-11', + 'account_proof_account_name' => '示例合作公司', 'account_proof_bank_name' => '示例银行', + 'account_proof_bank_account' => '0000000000000000', + 'account_change_date' => '2026-10-11', 'old_account_name' => '原收款人', + 'old_account_number' => '0000000000000000', 'old_account_stop_date' => '2026-10-11', + 'new_account_effective_date' => '2026-10-11', 'new_account_name' => '新收款人', + 'new_bank_name' => '示例银行', 'new_bank_account' => '0000000000000000', + 'former_company_name' => '示例原公司', 'former_legal_representative' => '原法人', + 'entity_change_date' => '2026-10-11', 'changed_company_name' => '示例新公司', + 'changed_company_start_date' => '2026-10-11', 'secondary_operator_name' => '新法人', + 'contract_partner_name' => '示例合作公司', 'shared_courier_names' => ['示例快递'], + 'cooperation_party_a_name' => '示例甲方公司', 'cooperation_party_a_phone' => '00000000000', + 'cooperation_party_b_name' => '示例乙方公司', 'cooperation_party_b_phone' => '00000000000', + 'cooperation_start_date' => '2026-10-11', 'cooperation_end_date' => '2027-10-10', + 'principal_name' => '示例委托方', 'principal_id_number' => 'EXAMPLE-ID', + 'trustee_name' => '示例受托方', 'trustee_id_number' => 'EXAMPLE-ID', + 'authorization_items' => ['1', '2', '3', '4'], 'bill_counterparty' => '示例对账方', + 'loan_counterparty' => '示例借支方', 'payment_counterparty' => '示例付款方', + 'authorization_start_date' => '2026-10-11', 'authorization_end_date' => '2027-10-10', + ]; + $signature = new CourierAgreementSignature([ + 'business_no' => 'AGR-LAYOUT-TEST', 'template_code' => CourierAgreementSignature::DOCUMENTS[$type]['code'], + 'document_type' => $type, 'payload' => $payload, + ]); + $frames = []; + $pdf = app('dompdf.wrapper'); + $this->app->instance('dompdf.wrapper', $pdf); + $pdf->getDomPDF()->setCallbacks([[ + 'event' => 'end_frame', + 'f' => function ($frame) use (&$frames, $pdf): void { + $node = $frame->get_node(); + if (! $node instanceof DOMElement || ! preg_match('/(?:blank|handwriting|sign-grid__line|contract-signatures__title|contract-signatures__line)/', $node->getAttribute('class'))) { + return; + } + $position = $frame->get_position(); + $frames[] = [ + 'class' => $node->getAttribute('class'), + 'page' => $pdf->getDomPDF()->getCanvas()->get_page_number(), + 'x' => $position['x'], 'y' => $position['y'], + 'width' => $frame->get_margin_width(), 'height' => $frame->get_margin_height(), + ]; + }, + ]]); + app(CourierAgreementPdf::class)->render($signature); + $this->app->forgetInstance('dompdf.wrapper'); + + return [$frames, $pdf->getDomPDF()->getCanvas()->get_page_count()]; + } +}