4034 lines
232 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@php($agreementTasks = $agreementTasks ?? collect())
@php($agreementQuoteSignatures = $agreementQuoteSignatures ?? collect())
@php($agreementSubjects = $agreementSubjects ?? collect())
@php($agreementCourierNames = collect($agreementCourierNames ?? []))
@php($agreementCourierAccounts = $agreementCourierAccounts ?? [])
@php($agreementSupplierOptions = $agreementSupplierOptions ?? [])
@php($supplierContractTemplates = \App\Support\SupplierCooperationTemplates::TEMPLATES)
@php($supplierContractRequestKey = (string) \Illuminate\Support\Str::uuid())
@php($agreementQuoteVersions = $agreementQuoteVersions ?? collect())
@php($agreementCooperationSecondaryEsignAccount = '18052733960')
@php($agreementDefaultSubject = $agreementSubjects->firstWhere('is_default', true) ?: $agreementSubjects->first())
@php($agreementCompanyName = $agreementDefaultSubject?->name ?: company()?->name ?: '当前公司')
@php($agreementSubjectPayload = $agreementSubjects->map(fn ($subject) => ['id' => $subject->id, 'name' => $subject->name, 'unified_social_credit_code' => $subject->unified_social_credit_code, 'is_default' => (bool) $subject->is_default])->values())
@php($esignConfigured = \App\Services\Esign\EsignClient::configured())
@php($agreementSearch = trim((string) request('agreement_search', '')))
@php($agreementStatus = trim((string) request('agreement_status', '')))
@php($agreementType = trim((string) request('agreement_type', '')))
@php($agreementScope = trim((string) request('agreement_scope', $agreementStatus === 'archived' ? 'archived' : 'active')))
@php($agreementScope = in_array($agreementScope, ['active', 'archived', 'all'], true) ? $agreementScope : 'active')
@php($agreementPaymentPrefill = \App\Business\CourierProfileData::agreementPrefill(request('payment_account')))
@php($agreementFiltersActive = $agreementSearch !== '' || $agreementStatus !== '' || $agreementType !== '')
<section class="agreement-workspace" aria-label="协议签署" data-agreement-signing>
<style>
.agreement-workspace {
--agreement-accent: var(--vip-content-accent-dark, #856632);
--agreement-accent-hover: #6A5129;
--agreement-accent-soft: var(--vip-content-accent-soft, #F7F0DE);
--agreement-gold: var(--vip-content-accent, #B9954F);
--agreement-border: var(--vip-border, #D8D2C7);
--agreement-ink: var(--vip-content-ink, #171717);
--agreement-muted: var(--vip-content-muted, #595959);
--agreement-surface: var(--vip-surface, #FFFFFF);
--agreement-success: var(--vip-success, #53793E);
--agreement-warning: var(--vip-warning, #935F07);
display: grid;
gap: 1rem;
min-width: 0;
margin-top: 1.5rem;
color: var(--agreement-ink);
font-family: JetBrains Mono, "Microsoft YaHei", "PingFang SC", monospace;
font-size: 0.8125rem;
letter-spacing: 0;
}
.agreement-workspace *,
.agreement-workspace *::before,
.agreement-workspace *::after {
box-sizing: border-box;
}
.agreement-workspace [hidden] {
display: none !important;
}
.supplier-contract-body { line-height: 1.8; }
.supplier-contract-body .supplier-contract-heading { font-size: 14px; margin: 18px 0 8px; }
.supplier-contract-paragraph { margin: 0 0 8px; overflow-wrap: anywhere; }
.supplier-contract-table { width: 100%; border-collapse: collapse; table-layout: fixed; margin: 12px 0; }
.supplier-contract-table td { border: 1px solid var(--agreement-border); padding: 6px; vertical-align: top; }
.supplier-contract-signatures { width: 100%; table-layout: fixed; margin: 18px 0; }
.supplier-contract-signatures td { width: 50%; vertical-align: top; padding: 8px; }
.supplier-contract-signatures p { margin: 0 0 8px; }
.supplier-contract-seal-space { height: 85px; }
.supplier-contract-image { margin: 12px 0; text-align: center; }
.supplier-contract-image img { max-width: 100%; height: auto; }
.agreement-tabs,
.agreement-panel {
min-width: 0;
border: 1px solid var(--agreement-border);
border-radius: 12px;
background: var(--agreement-surface);
}
.agreement-tabs {
display: flex;
min-height: 80px;
align-items: stretch;
justify-content: space-between;
gap: 1rem;
padding: 0 1rem 0 1.5rem;
overflow-x: auto;
}
.agreement-tab-list {
display: flex;
flex: 0 0 auto;
gap: 2rem;
min-height: 80px;
}
.agreement-tab {
position: relative;
display: inline-flex;
min-width: 7rem;
height: 80px;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0 0.25rem;
border: 0;
background: transparent;
color: var(--agreement-muted);
font: inherit;
font-size: 0.875rem;
font-weight: 600;
white-space: nowrap;
cursor: pointer;
transition: color 150ms ease;
}
.agreement-tab::after {
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 3px;
background: transparent;
content: '';
}
.agreement-tab:hover,
.agreement-tab[aria-selected="true"] {
color: var(--agreement-accent);
}
.agreement-tab[aria-selected="true"]::after {
background: var(--agreement-gold);
}
.agreement-tab:focus-visible,
.agreement-button:focus-visible,
.agreement-icon-button:focus-visible,
.agreement-inline-button:focus-visible,
.agreement-modal-close:focus-visible,
.agreement-control:focus-visible {
outline: 0;
box-shadow: 0 0 0 3px rgba(133, 102, 50, 0.2);
}
.agreement-tab .material-icons-outlined {
font-size: 20px;
}
.agreement-connection {
display: inline-flex;
flex: 0 0 auto;
align-items: center;
gap: 0.45rem;
align-self: center;
color: var(--agreement-warning);
font-size: 0.75rem;
font-weight: 600;
white-space: nowrap;
}
.agreement-connection .material-icons-outlined {
font-size: 18px;
}
.agreement-status {
display: inline-flex;
min-height: 24px;
align-items: center;
gap: 0.3rem;
padding: 0 0.55rem;
border: 1px solid currentColor;
border-radius: 999px;
font-size: 0.75rem;
font-weight: 600;
white-space: nowrap;
}
.agreement-status--warning {
color: var(--agreement-warning);
}
.agreement-status--success {
color: var(--agreement-success);
}
.agreement-status--danger {
color: var(--agreement-danger, #B80000);
}
.agreement-status-cell {
min-width: 13rem;
}
.agreement-error-summary {
display: block;
max-width: 24rem;
margin-top: 0.4rem;
color: var(--agreement-danger, #B80000);
font-size: 0.75rem;
line-height: 1.45;
overflow-wrap: anywhere;
white-space: normal;
}
.agreement-panel[hidden] {
display: none;
}
.agreement-panel {
overflow: hidden;
}
.agreement-filter-bar {
display: grid;
grid-template-columns: minmax(14rem, 1.4fr) repeat(2, minmax(9rem, 0.65fr)) auto;
align-items: end;
gap: 0.75rem;
padding: 1rem;
border-bottom: 1px solid var(--agreement-border);
}
.agreement-scope-bar {
display: flex;
flex-wrap: wrap;
gap: 1rem;
padding: 0 1rem;
border-bottom: 1px solid var(--agreement-border);
}
.agreement-scope-link {
display: inline-flex;
align-items: center;
gap: 0.35rem;
min-height: 42px;
border-bottom: 3px solid transparent;
color: var(--agreement-muted);
font-size: 0.75rem;
font-weight: 600;
text-decoration: none;
}
.agreement-scope-link:hover,
.agreement-scope-link[aria-current="page"] {
color: var(--agreement-accent);
}
.agreement-scope-link[aria-current="page"] {
border-bottom-color: var(--agreement-gold);
}
.agreement-scope-link:focus-visible {
outline: 2px solid var(--agreement-accent);
outline-offset: 2px;
}
.agreement-scope-link .material-icons-outlined {
font-size: 17px;
}
.agreement-archive-meta {
display: block;
max-width: 24rem;
margin-top: 0.35rem;
color: var(--agreement-muted);
font-size: 0.75rem;
line-height: 1.4;
white-space: normal;
overflow-wrap: anywhere;
}
.agreement-archive-meta strong {
margin-right: 0.4rem;
color: var(--agreement-ink);
font-weight: 600;
}
.agreement-button--compact {
min-height: 30px;
height: 30px;
padding: 0 0.6rem;
font-size: 0.75rem;
}
.agreement-task-error:not(:empty) {
margin: 0.75rem 1rem;
}
.agreement-archive-dialog .agreement-modal__body {
display: grid;
gap: 1rem;
}
.agreement-field {
display: grid;
gap: 0.35rem;
min-width: 0;
}
.agreement-field label,
.agreement-field-label,
.agreement-table th {
color: var(--agreement-muted);
font-size: 0.75rem;
font-weight: 600;
}
.agreement-control {
width: 100%;
min-width: 0;
height: 34px;
padding: 0 0.65rem;
border: 1px solid var(--agreement-border);
border-radius: 8px;
background: var(--agreement-surface);
color: var(--agreement-ink);
font: inherit;
font-size: 0.8125rem;
}
textarea.agreement-control {
min-height: 88px;
height: auto;
padding-top: 0.55rem;
padding-bottom: 0.55rem;
resize: vertical;
}
.agreement-control:hover {
border-color: #B8AE9D;
}
.agreement-control:focus {
border-color: var(--agreement-accent);
outline: 0;
box-shadow: 0 0 0 3px rgba(133, 102, 50, 0.2);
}
.agreement-control[readonly],
.agreement-control:disabled {
background: #F3F1EC;
color: var(--agreement-muted);
}
.agreement-courier-search-wrap {
position: relative;
}
.agreement-courier-native-select--enhanced {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
clip-path: inset(50%);
border: 0;
}
.agreement-courier-options {
position: absolute;
z-index: 20;
top: calc(100% + 4px);
right: 0;
left: 0;
max-height: 16rem;
overflow: auto;
border: 1px solid var(--agreement-border);
border-radius: 8px;
background: var(--agreement-surface);
box-shadow: 0 4px 8px rgba(23, 23, 23, 0.1);
}
.agreement-courier-option {
min-height: 34px;
padding: 0.5rem 0.65rem;
color: var(--agreement-ink);
cursor: pointer;
}
.agreement-courier-option:hover,
.agreement-courier-option.is-active {
background: var(--agreement-accent-soft);
color: var(--agreement-accent);
}
.agreement-courier-options-status {
padding: 0.5rem 0.65rem;
border-top: 1px solid var(--agreement-border);
color: var(--agreement-muted);
font-size: 0.75rem;
}
.agreement-courier-native-select--enhanced:focus-visible,
.agreement-courier-search-wrap .agreement-control:focus-visible {
outline: 0;
box-shadow: 0 0 0 3px rgba(133, 102, 50, 0.2);
}
.agreement-search {
position: relative;
}
.agreement-search .material-icons-outlined {
position: absolute;
top: 50%;
left: 0.65rem;
color: var(--agreement-muted);
font-size: 18px;
transform: translateY(-50%);
pointer-events: none;
}
.agreement-search .agreement-control {
padding-left: 2.15rem;
}
.agreement-button,
.agreement-icon-button {
display: inline-flex;
height: 34px;
align-items: center;
justify-content: center;
gap: 0.4rem;
border: 1px solid var(--agreement-border);
border-radius: 8px;
background: var(--agreement-surface);
color: var(--agreement-ink);
font: inherit;
font-size: 0.8125rem;
font-weight: 500;
white-space: nowrap;
cursor: pointer;
}
.agreement-button {
min-width: 6.5rem;
padding: 0 0.875rem;
}
.agreement-icon-button {
width: 34px;
padding: 0;
}
.agreement-button .material-icons-outlined,
.agreement-icon-button .material-icons-outlined {
font-size: 18px;
}
.agreement-button:hover,
.agreement-icon-button:hover {
border-color: var(--agreement-accent);
background: #FBF8F0;
}
.agreement-button--primary {
border-color: var(--agreement-accent);
background: var(--agreement-accent);
color: #FFFFFF;
}
.agreement-button--primary:hover {
border-color: var(--agreement-accent-hover);
background: var(--agreement-accent-hover);
}
.agreement-button--danger {
color: var(--agreement-danger, #B80000);
}
.agreement-button--danger:hover {
border-color: var(--agreement-danger, #B80000);
background: #FFF5F5;
}
.agreement-button:disabled,
.agreement-icon-button:disabled {
border-color: var(--agreement-border);
background: #E9E6DF;
color: #6B6862;
cursor: not-allowed;
}
.agreement-table-wrap {
width: 100%;
overflow-x: auto;
}
.agreement-table {
width: 100%;
min-width: 760px;
border-collapse: collapse;
font-size: 0.78125rem;
}
.agreement-table th,
.agreement-table td {
padding: 0.75rem 1rem;
border-bottom: 1px solid #E8E3DA;
text-align: left;
vertical-align: middle;
}
.agreement-table th {
background: #FBF8F0;
}
.agreement-table tbody tr:not(.agreement-empty-row):hover {
background: #FCFAF5;
}
.agreement-empty-row td {
padding: 3rem 1rem;
border-bottom: 0;
text-align: center;
}
.agreement-empty {
display: grid;
max-width: 32rem;
justify-items: center;
gap: 0.55rem;
margin: 0 auto;
}
.agreement-empty__icon {
display: grid;
width: 42px;
height: 42px;
place-items: center;
border-radius: 8px;
background: var(--agreement-accent-soft);
color: var(--agreement-accent);
}
.agreement-empty__icon .material-icons-outlined {
font-size: 22px;
}
.agreement-empty strong {
font-size: 0.875rem;
font-weight: 600;
}
.agreement-empty p {
margin: 0 0 0.35rem;
color: var(--agreement-muted);
line-height: 1.5;
}
.agreement-panel-footnote {
display: flex;
align-items: flex-start;
gap: 0.5rem;
padding: 0.75rem 1rem;
border-top: 1px solid var(--agreement-border);
background: #FAF9F6;
color: var(--agreement-muted);
font-size: 0.75rem;
line-height: 1.5;
}
.agreement-panel-footnote .material-icons-outlined {
flex: 0 0 auto;
color: var(--agreement-accent);
font-size: 18px;
}
.agreement-request-layout {
display: grid;
grid-template-columns: minmax(0, 1.7fr) minmax(320px, 0.72fr);
min-height: 680px;
}
.agreement-request-form {
display: grid;
min-width: 0;
grid-template-rows: auto minmax(0, 1fr) auto;
border-right: 1px solid var(--agreement-border);
}
.agreement-request-header,
.agreement-preview-header {
display: flex;
min-height: 52px;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
padding: 0.75rem 1rem;
border-bottom: 1px solid var(--agreement-border);
background: #FAF9F6;
}
.agreement-request-title,
.agreement-preview-title {
display: flex;
align-items: center;
gap: 0.5rem;
margin: 0;
font-size: 0.875rem;
font-weight: 600;
}
.agreement-request-title .material-icons-outlined,
.agreement-preview-title .material-icons-outlined {
color: var(--agreement-accent);
font-size: 19px;
}
.agreement-request-body {
display: grid;
align-content: start;
gap: 1rem;
padding: 1rem;
}
.agreement-form-section {
min-width: 0;
}
.agreement-section-heading {
display: flex;
min-height: 32px;
align-items: center;
margin: 0 0 0.75rem;
padding: 0 0.75rem;
border-bottom: 1px solid var(--agreement-border);
background: #FAF9F6;
font-size: 0.78125rem;
font-weight: 600;
}
.agreement-form-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.875rem;
}
.agreement-field--full {
grid-column: 1 / -1;
}
.agreement-required {
color: #B80000;
}
.agreement-help {
margin: 0;
color: var(--agreement-muted);
font-size: 0.6875rem;
line-height: 1.45;
}
.agreement-field-label-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.5rem;
}
.agreement-inline-button {
display: inline-flex;
min-height: 26px;
align-items: center;
gap: 0.25rem;
padding: 0 0.55rem;
border: 1px solid var(--agreement-border);
border-radius: 6px;
background: var(--agreement-surface);
color: var(--agreement-accent);
font: inherit;
font-size: 0.6875rem;
font-weight: 600;
cursor: pointer;
}
.agreement-inline-button:hover {
border-color: var(--agreement-accent);
background: var(--agreement-accent-soft);
}
.agreement-inline-button .material-icons-outlined {
font-size: 15px;
}
.agreement-shared-courier-list {
display: grid;
gap: 0.5rem;
}
.agreement-shared-courier-row {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: 0.5rem;
align-items: center;
}
.agreement-shared-courier-row .agreement-icon-button {
flex: 0 0 auto;
}
.agreement-shared-courier-add {
justify-self: start;
margin-top: 0.15rem;
}
.agreement-modal {
position: fixed;
z-index: 1000;
inset: 0;
display: grid;
padding: 1rem;
place-items: center;
}
.agreement-modal__backdrop {
position: absolute;
inset: 0;
background: rgba(23, 23, 23, 0.46);
}
.agreement-modal__dialog {
position: relative;
display: grid;
width: min(100%, 560px);
max-height: min(720px, calc(100vh - 2rem));
grid-template-rows: auto minmax(0, 1fr) auto;
overflow: hidden;
border: 1px solid var(--agreement-border);
border-radius: 12px;
background: var(--agreement-surface);
box-shadow: 0 4px 8px rgba(23, 23, 23, 0.16);
}
.agreement-modal__header,
.agreement-modal__footer {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
padding: 0.85rem 1rem;
border-bottom: 1px solid var(--agreement-border);
background: #FAF9F6;
}
.agreement-modal__footer {
justify-content: flex-end;
border-top: 1px solid var(--agreement-border);
border-bottom: 0;
}
.agreement-modal__title {
display: flex;
align-items: center;
gap: 0.45rem;
margin: 0;
font-size: 0.875rem;
font-weight: 600;
}
.agreement-modal__title .material-icons-outlined {
color: var(--agreement-accent);
font-size: 19px;
}
.agreement-modal-close {
display: inline-grid;
width: 30px;
height: 30px;
padding: 0;
place-items: center;
border: 1px solid transparent;
border-radius: 6px;
background: transparent;
color: var(--agreement-muted);
cursor: pointer;
}
.agreement-modal-close:hover {
border-color: var(--agreement-border);
background: var(--agreement-surface);
color: var(--agreement-ink);
}
.agreement-modal__body {
display: grid;
align-content: start;
gap: 1rem;
overflow-y: auto;
padding: 1rem;
}
.agreement-modal__hint {
display: flex;
align-items: flex-start;
gap: 0.45rem;
margin: 0;
padding: 0.65rem 0.75rem;
border: 1px solid #D9BD88;
border-radius: 8px;
background: var(--agreement-accent-soft);
color: #5B4322;
font-size: 0.75rem;
line-height: 1.45;
}
.agreement-modal__hint .material-icons-outlined {
flex: 0 0 auto;
color: var(--agreement-accent);
font-size: 17px;
}
.agreement-subject-list {
display: grid;
gap: 0.5rem;
}
.agreement-subject-item {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
align-items: center;
gap: 0.75rem;
padding: 0.7rem 0.75rem;
border: 1px solid var(--agreement-border);
border-radius: 8px;
}
.agreement-subject-item--default {
border-color: #D9BD88;
background: #FCFAF5;
}
.agreement-subject-item__name {
display: flex;
min-width: 0;
align-items: center;
flex-wrap: wrap;
gap: 0.4rem;
font-weight: 600;
}
.agreement-subject-item__name-text {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.agreement-subject-item__code {
margin-top: 0.2rem;
color: var(--agreement-muted);
font-size: 0.6875rem;
}
.agreement-subject-item__actions {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: 0.4rem;
}
.agreement-subject-item__actions .agreement-button {
min-width: auto;
height: 30px;
padding: 0 0.65rem;
font-size: 0.75rem;
}
.agreement-subject-empty {
padding: 1rem;
border: 1px dashed var(--agreement-border);
border-radius: 8px;
color: var(--agreement-muted);
text-align: center;
}
.agreement-subject-form {
display: grid;
gap: 0.75rem;
padding-top: 1rem;
border-top: 1px solid var(--agreement-border);
}
.agreement-subject-form__title {
margin: 0;
font-size: 0.8125rem;
font-weight: 600;
}
.agreement-subject-form__actions {
display: flex;
justify-content: flex-end;
gap: 0.5rem;
}
.agreement-subject-form__error {
min-height: 0;
margin: 0;
color: var(--agreement-danger, #B80000);
font-size: 0.75rem;
}
.agreement-subject-form__error:empty {
display: none;
}
body:has(.agreement-modal:not([hidden])) {
overflow: hidden;
}
.agreement-template-note {
display: grid;
grid-template-columns: auto minmax(0, 1fr);
grid-column: 1 / -1;
gap: 0.6rem;
padding: 0.7rem 0.75rem;
border: 1px solid #D9BD88;
border-radius: 8px;
background: var(--agreement-accent-soft);
color: #5B4322;
}
.agreement-template-note > .material-icons-outlined {
color: var(--agreement-accent);
font-size: 19px;
}
.agreement-template-note strong {
display: block;
font-size: 0.78125rem;
}
.agreement-template-note p {
margin: 0.15rem 0 0;
font-size: 0.6875rem;
line-height: 1.45;
}
.agreement-form-error {
display: flex;
align-items: center;
gap: 0.35rem;
min-height: 22px;
margin-top: 0.75rem;
color: #B80000;
font-size: 0.75rem;
}
.agreement-form-error:empty {
min-height: 0;
margin-top: 0;
}
.agreement-form-error .material-icons-outlined {
font-size: 17px;
}
.agreement-partner-types {
margin: 0;
padding: 0;
border: 0;
min-width: 0;
}
.agreement-partner-types legend {
margin-bottom: 0.5rem;
}
.agreement-archive-options {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.75rem;
}
.agreement-archive-fieldset {
min-width: 0;
margin: 0;
padding: 0;
border: 0;
}
.agreement-archive-fieldset .agreement-section-heading {
width: 100%;
}
.agreement-archive-choice {
display: grid;
grid-template-columns: auto minmax(0, 1fr);
align-items: start;
gap: 0.55rem;
min-height: 58px;
padding: 0.7rem 0.75rem;
border: 1px solid var(--agreement-border);
border-radius: 8px;
cursor: pointer;
}
.agreement-archive-choice:hover,
.agreement-archive-choice:has(input:checked) {
border-color: var(--agreement-accent);
background: #FCFAF5;
}
.agreement-archive-choice input {
margin: 0.15rem 0 0;
accent-color: var(--agreement-accent);
}
.agreement-archive-choice strong {
display: block;
font-size: 0.75rem;
}
.agreement-archive-choice span span {
display: block;
margin-top: 0.15rem;
color: var(--agreement-muted);
font-size: 0.6875rem;
line-height: 1.4;
}
.agreement-request-actions {
display: flex;
min-height: 66px;
align-items: center;
justify-content: flex-end;
gap: 0.5rem;
padding: 1rem;
border-top: 1px solid var(--agreement-border);
background: #FAF9F6;
}
.agreement-preview-pane {
display: grid;
min-width: 0;
grid-template-rows: auto minmax(0, 1fr);
background: #F1F0EC;
}
.agreement-preview-header {
background: #F7F5F0;
}
.agreement-preview-meta {
color: var(--agreement-muted);
font-size: 0.6875rem;
}
.agreement-preview-scroll {
min-height: 0;
max-height: 760px;
padding: 1rem;
overflow: auto;
scrollbar-color: var(--agreement-gold) #E3E0D9;
scrollbar-width: thin;
}
.agreement-preview-paper {
width: 100%;
max-width: 470px;
min-height: 650px;
margin: 0 auto;
padding: 2rem 1.5rem;
border: 1px solid var(--agreement-border);
border-radius: 8px;
background: #FFFFFF;
color: #202020;
font-family: "Microsoft YaHei", "PingFang SC", sans-serif;
font-size: 0.75rem;
line-height: 1.8;
}
.agreement-preview-paper h3 {
margin: 0 0 1.5rem;
font-size: 1rem;
font-weight: 700;
text-align: center;
}
.agreement-preview-paper h4 {
margin: 1.25rem 0 0.5rem;
font-size: 0.82rem;
font-weight: 700;
}
.agreement-preview-paper p {
margin: 0.75rem 0;
}
.agreement-checkbox-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.65rem;
}
.agreement-checkbox-choice {
display: grid;
grid-template-columns: auto minmax(0, 1fr);
align-items: start;
gap: 0.55rem;
min-height: 3.25rem;
padding: 0.75rem;
border: 1px solid var(--agreement-border);
border-radius: 6px;
background: var(--agreement-surface);
color: var(--agreement-ink);
cursor: pointer;
}
.agreement-checkbox-choice:hover,
.agreement-checkbox-choice:has(input:checked) {
border-color: var(--agreement-accent);
background: var(--agreement-accent-soft);
}
.agreement-checkbox-choice input {
margin: 0.18rem 0 0;
accent-color: var(--agreement-accent);
}
.agreement-checkbox-choice span {
line-height: 1.45;
}
.agreement-preview-account {
display: grid;
gap: 0.45rem;
margin: 1.5rem 0;
padding: 0.85rem 1rem;
border: 1px solid #E3DED4;
border-radius: 8px;
background: #FAF9F6;
}
.agreement-preview-account div {
display: grid;
grid-template-columns: 5rem minmax(0, 1fr);
gap: 0.5rem;
}
.agreement-preview-quote-matrix {
max-width: 100%;
margin: 1rem 0;
overflow-x: auto;
}
.agreement-preview-quote-matrix table {
width: 100%;
border-collapse: collapse;
font-size: 0.72rem;
}
.agreement-preview-quote-matrix th,
.agreement-preview-quote-matrix td {
min-width: 4.5rem;
border: 1px solid #E3DED4;
padding: 0.35rem 0.45rem;
text-align: left;
vertical-align: top;
}
.agreement-preview-quote-matrix th {
background: #F3EEE4;
font-weight: 600;
}
.agreement-preview-parties {
display: grid;
gap: 0.45rem;
margin: 1.5rem 0;
padding: 0.85rem 1rem;
border: 1px solid #E3DED4;
border-radius: 8px;
background: #FAF9F6;
}
.agreement-preview-party-phone {
display: inline-block;
margin-left: 2rem;
}
.agreement-preview-value {
min-width: 2.5rem;
padding: 0 0.2rem;
border-bottom: 1px solid #D9BD88;
background: #FFF8E8;
color: var(--agreement-ink);
font-weight: 600;
overflow-wrap: anywhere;
}
.agreement-preview-signature {
margin-top: 2.5rem;
padding: 0;
text-align: left;
}
.agreement-preview-signature--split {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 1.5rem;
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;
}
.agreement-preview-list li {
margin: 0.45rem 0;
padding-left: 0.15rem;
}
.agreement-preview-page-number {
margin-top: 3rem;
color: var(--agreement-muted);
font-size: 0.6875rem;
text-align: center;
}
.agreement-template-summary {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
padding: 1rem;
border-bottom: 1px solid var(--agreement-border);
}
.agreement-template-summary__copy {
min-width: 0;
}
.agreement-template-summary strong {
display: block;
font-size: 0.875rem;
font-weight: 600;
}
.agreement-template-summary p {
margin: 0.25rem 0 0;
color: var(--agreement-muted);
font-size: 0.75rem;
}
.agreement-template-table .agreement-status {
min-height: 22px;
}
@media (max-width: 960px) {
.agreement-filter-bar {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.agreement-request-layout {
grid-template-columns: 1fr;
}
.agreement-request-form {
border-right: 0;
}
.agreement-preview-pane {
border-top: 1px solid var(--agreement-border);
}
.agreement-preview-scroll {
max-height: 660px;
}
}
@media (max-width: 680px) {
.agreement-tabs {
display: block;
padding: 0;
}
.agreement-tab-list {
gap: 0;
}
.agreement-tab {
min-width: 7.5rem;
}
.agreement-connection {
display: none;
}
.agreement-filter-bar,
.agreement-form-grid,
.agreement-checkbox-grid,
.agreement-archive-options {
grid-template-columns: 1fr;
}
.agreement-field--full {
grid-column: auto;
}
.agreement-request-actions {
display: grid;
grid-template-columns: 1fr;
}
.agreement-request-actions .agreement-button {
width: 100%;
}
.agreement-template-summary {
align-items: flex-start;
flex-direction: column;
}
}
@media (prefers-reduced-motion: reduce) {
.agreement-tab {
transition: none;
}
}
</style>
<div class="agreement-tabs">
<div class="agreement-tab-list" role="tablist" aria-label="协议签署工作区">
<button class="agreement-tab" type="button" role="tab" id="agreement-tab-tasks" aria-controls="agreement-panel-tasks" aria-selected="true" data-agreement-tab="tasks">
<span class="material-icons-outlined" aria-hidden="true">assignment</span>
<span>签署任务</span>
</button>
<button class="agreement-tab" type="button" role="tab" id="agreement-tab-create" aria-controls="agreement-panel-create" aria-selected="false" tabindex="-1" data-agreement-tab="create">
<span class="material-icons-outlined" aria-hidden="true">add_circle_outline</span>
<span>发起签章</span>
</button>
<button class="agreement-tab" type="button" role="tab" id="agreement-tab-templates" aria-controls="agreement-panel-templates" aria-selected="false" tabindex="-1" data-agreement-tab="templates">
<span class="material-icons-outlined" aria-hidden="true">description</span>
<span>模板管理</span>
</button>
</div>
<span class="agreement-connection" title="{{ $esignConfigured ? 'E签宝应用已配置,可推送签署任务' : '当前环境尚未配置E签宝应用凭证' }}">
<span class="material-icons-outlined" aria-hidden="true">{{ $esignConfigured ? 'link' : 'link_off' }}</span>
{{ $esignConfigured ? 'E签宝已连接 · ' . (config('services.esign.environment', 'sandbox') === 'production' ? '正式' : '沙箱') : 'E签宝未连接' }}
</span>
</div>
<section class="agreement-panel" id="agreement-panel-tasks" role="tabpanel" aria-labelledby="agreement-tab-tasks" data-agreement-panel="tasks">
@php($scopeQuery = request()->except(['agreement_scope', 'agreement_status', 'agreement_task_page', 'agreement_quote_page']))
<nav class="agreement-scope-bar" aria-label="任务归档视图">
@foreach (['active' => ['inbox', '待处理'], 'all' => ['view_list', '全部任务'], 'archived' => ['inventory_2', '已归档']] as $scope => $scopeLabel)
<a class="agreement-scope-link" data-task-scope="{{ $scope }}" href="{{ url()->current() . '?' . http_build_query(array_merge($scopeQuery, ['agreement_view' => 'tasks', 'agreement_scope' => $scope])) }}" @if ($agreementScope === $scope) aria-current="page" @endif>
<span class="material-icons-outlined" aria-hidden="true">{{ $scopeLabel[0] }}</span>
{{ $scopeLabel[1] }}
</a>
@endforeach
</nav>
<p class="agreement-form-error agreement-task-error" role="alert" data-task-load-error></p>
<form class="agreement-filter-bar" method="GET" action="{{ url()->current() }}" data-task-filter-form>
<input type="hidden" name="agreement_view" value="tasks">
<input type="hidden" name="agreement_scope" value="{{ $agreementScope }}">
<div class="agreement-field">
<label for="agreement-task-search">搜索任务</label>
<div class="agreement-search">
<span class="material-icons-outlined" aria-hidden="true">search</span>
<input class="agreement-control" id="agreement-task-search" name="agreement_search" type="search" value="{{ $agreementSearch }}" placeholder="任务编号、合作方名称或签署人" autocomplete="off" data-task-filter>
</div>
</div>
<div class="agreement-field">
<label for="agreement-task-status">签署状态</label>
<select class="agreement-control" id="agreement-task-status" name="agreement_status" data-task-filter>
<option value="">全部状态</option>
@if ($agreementScope !== 'archived')
<option value="prepared" @selected($agreementStatus === 'prepared')>待推送</option>
<option value="sending" @selected($agreementStatus === 'sending')>推送中</option>
<option value="signing" @selected($agreementStatus === 'signing')>待签署</option>
<option value="completed" @selected($agreementStatus === 'completed')>签署完成,待归档</option>
<option value="revoked" @selected($agreementStatus === 'revoked')>已撤销</option>
<option value="rejected" @selected($agreementStatus === 'rejected')>已拒签</option>
<option value="expired" @selected($agreementStatus === 'expired')>已过期</option>
<option value="failed" @selected($agreementStatus === 'failed')>处理失败</option>
<option value="unknown" @selected($agreementStatus === 'unknown')>状态未知</option>
@endif
@if ($agreementScope !== 'active')
<option value="archived" @selected($agreementStatus === 'archived')>已签署并归档</option>
@endif
</select>
</div>
<div class="agreement-field">
<label for="agreement-task-type">业务类型</label>
<select class="agreement-control" id="agreement-task-type" name="agreement_type" data-task-filter>
<option value="">全部类型</option>
<option value="account-change" @selected($agreementType === 'account-change')>收款账户变更</option>
<option value="account-proof" @selected($agreementType === 'account-proof')>收款账户证明</option>
<option value="entity-change" @selected($agreementType === 'entity-change')>公司主体变更</option>
<option value="shared-contract" @selected($agreementType === 'shared-contract')>共用合同证明</option>
<option value="cooperation-contract" @selected($agreementType === 'cooperation-contract')>合作合同</option>
<option value="authorization" @selected($agreementType === 'authorization')>授权委托书</option>
<option value="quote-confirmation" @selected($agreementType === 'quote-confirmation')>报价确认单</option>
</select>
</div>
<button class="agreement-button agreement-button--primary" type="submit">
<span class="material-icons-outlined" aria-hidden="true">search</span>
查询
</button>
<button class="agreement-button" type="button" data-task-reset>
<span class="material-icons-outlined" aria-hidden="true">restart_alt</span>
重置
</button>
</form>
<div class="agreement-table-wrap">
<table class="agreement-table">
<thead>
<tr>
<th scope="col">任务编号</th>
<th scope="col">合作方类型</th>
<th scope="col">合作方名称</th>
<th scope="col">业务类型</th>
<th scope="col">签署状态</th>
<th scope="col">发起人</th>
<th scope="col">更新时间</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
@foreach ($agreementQuoteSignatures as $quoteSignature)
@php($quoteVersion = $quoteSignature->version)
@php($quoteError = $quoteSignature->lastErrorSummary())
<tr data-quote-task-row>
<td>{{ $quoteVersion?->version_code ?? ('报价版本 #' . $quoteSignature->quote_version_id) }}</td>
<td>快递公司</td>
<td>{{ $quoteVersion?->carrier_name ?? $quoteSignature->organization_name }}</td>
<td>报价确认单</td>
<td class="agreement-status-cell">
<span class="agreement-status agreement-status--{{ in_array($quoteSignature->status, ['archived', 'completed'], true) ? 'success' : (in_array($quoteSignature->status, ['failed', 'rejected', 'expired', 'revoked'], true) ? 'danger' : 'warning') }}">{{ $quoteSignature->statusLabel() }}</span>
@if ($quoteSignature->status === 'archived')
<span class="agreement-archive-meta"><strong>归档时间</strong>{{ optional($quoteSignature->archived_at)->format('Y-m-d H:i') ?: '时间未知' }}</span>
<span class="agreement-archive-meta"><strong>归档说明</strong>签署完成后自动归档</span>
@endif
@if ($quoteError)
<span class="agreement-error-summary" title="{{ $quoteError }}">{{ $quoteError }}</span>
@endif
</td>
<td>{{ $agreementCompanyName }}</td>
<td>{{ optional($quoteSignature->updated_at)->format('Y-m-d H:i') }}</td>
<td class="agreement-table-actions">
@if ($quoteSignature->esign_sign_flow_id && ! in_array($quoteSignature->status, ['archived', 'rejected', 'expired', 'revoked'], true))
<form method="POST" action="{{ route('business.courier-agreement-signatures.quotes.synchronize', $quoteSignature) }}">
@csrf
<button class="agreement-icon-button" type="submit" title="同步E签宝状态"><span class="material-icons-outlined" aria-hidden="true">sync</span></button>
</form>
@endif
@if ($quoteSignature->source_pdf_path)
<a class="agreement-icon-button" href="{{ route('business.courier-agreement-signatures.quotes.download', [$quoteSignature, 'source']) }}" title="下载报价确认单原文"><span class="material-icons-outlined" aria-hidden="true">picture_as_pdf</span></a>
@endif
@if ($quoteSignature->signed_pdf_path)
<a class="agreement-icon-button" href="{{ route('business.courier-agreement-signatures.quotes.download', [$quoteSignature, 'signed']) }}" title="下载已签署报价确认单"><span class="material-icons-outlined" aria-hidden="true">download</span></a>
@endif
@if ($quoteSignature->certificate_path)
<a class="agreement-icon-button" href="{{ route('business.courier-agreement-signatures.quotes.download', [$quoteSignature, 'certificate']) }}" title="下载签署完成证书"><span class="material-icons-outlined" aria-hidden="true">workspace_premium</span></a>
@endif
<form method="POST" action="{{ route('business.courier-agreement-signatures.quotes.destroy', $quoteSignature) }}" data-delete-task-form data-task-number="{{ $quoteVersion?->version_code ?? ('报价版本 #' . $quoteSignature->quote_version_id) }}" data-task-description="{{ $quoteVersion?->carrier_name ?? $quoteSignature->organization_name }} · 报价确认单 · {{ $quoteSignature->statusLabel() }}">
@csrf
@method('DELETE')
<input type="hidden" name="delete_confirmed" value="1">
<button class="agreement-button agreement-button--compact agreement-button--danger" type="button" data-delete-task-open title="删除签署任务"><span class="material-icons-outlined" aria-hidden="true">delete_outline</span>删除</button>
</form>
</td>
</tr>
@endforeach
@foreach ($agreementTasks as $task)
@php($taskError = $task->lastErrorSummary())
@php($taskFailed = $task->status === 'failed' || ($task->status === 'unknown' && $task->hasDefinitiveFailure()))
<tr data-agreement-task-row>
<td>{{ $task->business_no }}</td>
<td>{{ $task->partnerTypeLabel() }}</td>
<td>{{ $task->courier_name }}</td>
<td>{{ $task->documentLabel() }}</td>
<td class="agreement-status-cell">
<span class="agreement-status agreement-status--{{ in_array($task->status, ['archived', 'completed'], true) ? 'success' : ($taskFailed || in_array($task->status, ['rejected', 'expired', 'revoked'], true) ? 'danger' : 'warning') }}">{{ $task->statusLabel() }}</span>
@if ($task->status === 'archived')
<span class="agreement-archive-meta"><strong>归档时间</strong>{{ optional($task->archived_at)->format('Y-m-d H:i') ?: '时间未知' }}</span>
<span class="agreement-archive-meta"><strong>归档说明</strong>{{ $task->archiveReason() ?: '未记录说明' }}</span>
@endif
@if ($taskError)
<span class="agreement-error-summary" title="{{ $taskError }}">{{ $taskError }}</span>
@endif
</td>
<td>{{ $task->initiatorName() }}</td>
<td>{{ optional($task->updated_at)->format('Y-m-d H:i') }}</td>
<td class="agreement-table-actions">
@if ($task->esign_sign_flow_id && ! in_array($task->status, ['archived', 'rejected', 'expired', 'revoked'], true))
<form method="POST" action="{{ route('business.courier-agreement-signatures.synchronize', $task) }}">
@csrf
<button class="agreement-icon-button" type="submit" title="同步E签宝状态"><span class="material-icons-outlined" aria-hidden="true">sync</span></button>
</form>
@endif
@if ($task->status === 'completed' && $task->remote_status === '2' && $task->archiveMode() === 'manual')
<form method="POST" action="{{ route('business.courier-agreement-signatures.archive', $task) }}" data-archive-form data-task-number="{{ $task->business_no }}">
@csrf
<input type="hidden" name="archive_reason_code" data-archive-reason-code>
<input type="hidden" name="archive_note" data-archive-note>
<button class="agreement-button agreement-button--compact" type="button" data-archive-open title="人工确认并归档"><span class="material-icons-outlined" aria-hidden="true">archive</span>归档</button>
</form>
@endif
@if ($task->source_pdf_path)
<a class="agreement-icon-button" href="{{ route('business.courier-agreement-signatures.download', [$task, 'source']) }}" title="下载签署原文"><span class="material-icons-outlined" aria-hidden="true">picture_as_pdf</span></a>
@endif
@if ($task->signed_pdf_path)
<a class="agreement-icon-button" href="{{ route('business.courier-agreement-signatures.download', [$task, 'signed']) }}" title="下载已签署协议"><span class="material-icons-outlined" aria-hidden="true">download</span></a>
@endif
@if ($task->certificate_path)
<a class="agreement-icon-button" href="{{ route('business.courier-agreement-signatures.download', [$task, 'certificate']) }}" title="下载签署完成证书"><span class="material-icons-outlined" aria-hidden="true">workspace_premium</span></a>
@endif
@foreach ($task->credentialDocuments() as $credentialKey => $credential)
<a class="agreement-button agreement-button--compact" target="_blank" rel="noopener" href="{{ route('business.courier-agreement-signatures.download', [$task, 'credential-' . $credentialKey . (!empty($credential['signed_path']) ? '-signed' : '-source'), 'preview' => 1]) }}">预览{{ $credential['name'] }}</a>
<a class="agreement-button agreement-button--compact" href="{{ route('business.courier-agreement-signatures.download', [$task, 'credential-' . $credentialKey . '-source']) }}">{{ $credential['name'] }}原文</a>
@if (!empty($credential['signed_path']))
<a class="agreement-button agreement-button--compact" href="{{ route('business.courier-agreement-signatures.download', [$task, 'credential-' . $credentialKey . '-signed']) }}">{{ $credential['name'] }}已签署</a>
@endif
@endforeach
<form method="POST" action="{{ route('business.courier-agreement-signatures.destroy', $task) }}" data-delete-task-form data-task-number="{{ $task->business_no }}" data-task-description="{{ $task->courier_name }} · {{ $task->documentLabel() }} · {{ $task->statusLabel() }}">
@csrf
@method('DELETE')
<input type="hidden" name="delete_confirmed" value="1">
<button class="agreement-button agreement-button--compact agreement-button--danger" type="button" data-delete-task-open title="删除签署任务"><span class="material-icons-outlined" aria-hidden="true">delete_outline</span>删除</button>
</form>
</td>
</tr>
@endforeach
@if ($agreementTasks->isEmpty() && $agreementQuoteSignatures->isEmpty())
<tr class="agreement-empty-row">
<td colspan="8">
<div class="agreement-empty">
<span class="agreement-empty__icon">
<span class="material-icons-outlined" aria-hidden="true">assignment_late</span>
</span>
@if ($agreementFiltersActive)
<strong>没有匹配的签署任务</strong>
<p>请调整筛选条件后重新查询。</p>
@else
<strong>{{ $agreementScope === 'archived' ? '还没有已归档任务' : ($agreementScope === 'active' ? '暂无待处理任务' : '还没有协议签署任务') }}</strong>
<p>{{ $agreementScope === 'archived' ? '完成归档后可在这里检索和下载签署文件。' : '可新建签署任务,或在“全部任务”和“已归档”中查找历史文件。' }}</p>
@endif
<button class="agreement-button agreement-button--primary" type="button" data-start-agreement>
<span class="material-icons-outlined" aria-hidden="true">add</span>
新建签署任务
</button>
</div>
</td>
</tr>
@endif
</tbody>
</table>
</div>
@php($taskTotal = method_exists($agreementTasks, 'total') ? $agreementTasks->total() : $agreementTasks->count())
@php($quoteTotal = method_exists($agreementQuoteSignatures, 'total') ? $agreementQuoteSignatures->total() : $agreementQuoteSignatures->count())
@php($taskPages = method_exists($agreementTasks, 'lastPage') ? $agreementTasks->lastPage() : 0)
@php($quotePages = method_exists($agreementQuoteSignatures, 'lastPage') ? $agreementQuoteSignatures->lastPage() : 0)
<div class="agreement-panel-footnote">
<span>共 {{ $taskTotal + $quoteTotal }} 条 · 协议任务 {{ $taskTotal }} 条,报价确认单 {{ $quoteTotal }} 条</span>
@if (method_exists($agreementTasks, 'links') && $taskPages > 1)
<span>协议任务分页:</span>{{ $agreementTasks->links() }}
@endif
@if (method_exists($agreementQuoteSignatures, 'links') && $quotePages > 1)
<span>报价确认单分页:</span>{{ $agreementQuoteSignatures->links() }}
@endif
</div>
<div class="agreement-panel-footnote">
<span class="material-icons-outlined" aria-hidden="true">shield</span>
<span>签署完成只生成可核验的电子协议,不会自动启用新收款账户;账户变更仍需独立财务复核和原档案电话核验。</span>
</div>
</section>
<section class="agreement-panel" id="agreement-panel-create" role="tabpanel" aria-labelledby="agreement-tab-create" data-agreement-panel="create" hidden>
<div class="agreement-request-layout">
<form class="agreement-request-form" method="POST" enctype="multipart/form-data" action="{{ route('business.courier-agreement-signatures.store') }}" novalidate data-agreement-form data-signing-request-form>
@csrf
<input type="hidden" name="idempotency_key" value="{{ $supplierContractRequestKey }}">
<header class="agreement-request-header">
<h2 class="agreement-request-title"><span class="material-icons-outlined" aria-hidden="true">draw</span><span>发起签章请求</span></h2>
<span class="agreement-status agreement-status--{{ $esignConfigured ? 'success' : 'warning' }}">{{ $esignConfigured ? 'E签宝可用' : '沙箱未配置' }}</span>
</header>
<div class="agreement-request-body">
@if ($agreementPaymentPrefill)
<div class="agreement-template-note" role="status" data-payment-prefill-note style="border-color:#E3C98F;background:#FFF8E8">
<span class="material-icons-outlined" aria-hidden="true">campaign</span>
<div><strong>来自快递资料 · {{ $agreementPaymentPrefill['action'] }}:{{ $agreementPaymentPrefill['courier_name'] }}({{ $agreementPaymentPrefill['expcode'] }})</strong><p>已按打款信息预填「{{ $agreementPaymentPrefill['document_type'] === 'account-change' ? '收款账户变更' : '收款账户证明' }}」。请补齐 E 签宝账号、签署人等变更资料后推送给快递签署,签署完成后快递资料里这条打款信息显示为「已生效」。</p></div>
</div>
@endif
<section class="agreement-form-section" aria-labelledby="agreement-base-heading">
<h3 class="agreement-section-heading" id="agreement-base-heading">基础信息</h3>
<div class="agreement-form-grid">
<fieldset class="agreement-field agreement-field--full agreement-partner-types">
<legend class="agreement-field-label">合作方类型 <span class="agreement-required" aria-hidden="true">*</span></legend>
<div class="agreement-archive-options">
<label class="agreement-archive-choice"><input type="radio" name="partner_type" value="courier" checked data-partner-type><span><strong>快递公司</strong><span>选择快递资料,发起快递合作相关文件</span></span></label>
<label class="agreement-archive-choice"><input type="radio" name="partner_type" value="supplier" data-partner-type><span><strong>供应商</strong><span>按供应商简称、企业全称或编码查找</span></span></label>
</div>
</fieldset>
<div class="agreement-field">
<label for="agreement-courier"><span data-partner-name-label>快递公司</span> <span class="agreement-required" aria-hidden="true">*</span></label>
<div class="agreement-courier-search-wrap" data-courier-control>
<select class="agreement-control" id="agreement-courier" name="courier_name" data-courier-select required>
<option value="">请选择</option>
@if ($agreementCourierNames->isEmpty())
<option value="" disabled>暂无可选快递资料</option>
@endif
@foreach ($agreementCourierNames as $courierName)
<option value="{{ $courierName }}" data-esign-account="{{ $agreementCourierAccounts[$courierName] ?? '' }}">{{ $courierName }}</option>
@endforeach
</select>
<div class="agreement-courier-search-wrap" data-courier-search-wrap hidden>
<input class="agreement-control" id="agreement-courier-search" type="search" placeholder="输入快递名称搜索" autocomplete="off" role="combobox" aria-autocomplete="list" aria-haspopup="listbox" aria-expanded="false" aria-controls="agreement-courier-options" data-courier-search>
<div class="agreement-courier-options" id="agreement-courier-options" role="listbox" aria-label="快递资料" hidden data-courier-options></div>
</div>
</div>
<input type="hidden" name="supplier_id" data-signing-supplier-id disabled>
<p class="agreement-help" data-supplier-control hidden aria-live="polite">按供应商简称、企业全称或编码搜索,选择后自动带入易签宝账号。</p>
</div>
<div class="agreement-field">
<label for="agreement-document-type">文件类型 <span class="agreement-required" aria-hidden="true">*</span></label>
<select class="agreement-control" id="agreement-document-type" name="document_type" data-document-type required>
<option value="account-proof" data-partner-types="courier supplier" data-title="收款帐户资料证明" data-name="收款账户证明" data-code="TPL-ACCOUNT-CERT-V2" data-file="收款账户证明文件.doc" data-description="原文件:收款账户证明文件.doc;对方企业盖章或个人签字" selected>收款账户证明</option>
<option value="account-change" data-partner-types="courier supplier" data-title="收款帐户资料变更证明" data-name="收款账户变更" data-code="TPL-ACCOUNT-CHANGE-V1" data-file="收款账户变更证明.doc" data-description="原文件:收款账户变更证明.doc;对方企业盖章或个人签字">收款账户变更</option>
<option value="entity-change" data-partner-types="courier supplier" data-title="公司主体变更证明" data-name="公司主体变更" data-code="TPL-ENTITY-CHANGE-V1" data-file="公司主体变更证明.docx" data-description="原文件:公司主体变更证明.docx;变更前、变更后公司分别签字盖章">公司主体变更</option>
<option value="shared-contract" data-title="证明" data-name="共用合同证明" data-code="TPL-SHARED-CONTRACT-V1" data-file="共用合同证明.docx" data-description="物流商归属企业盖章确认共用合同及结算主体;也可选择个人实名签署">共用合同证明</option>
<option value="cooperation-contract" data-partner-types="courier supplier" data-title="服务协议" data-name="合作合同" data-code="TPL-COOPERATION-CONTRACT-V1" data-file="保丟不保损-合同发快递2024.8.doc" data-description="原文件:保丟不保损-合同发快递2024.8.doc;甲乙双方签署盖章">合作合同</option>
<option value="authorization" data-partner-types="courier supplier" data-title="授权委托书" data-name="授权委托书" data-code="TPL-AUTHORIZATION-V1" data-file="授权委托书(快递).docx" data-description="原文件:授权委托书(快递).docx;委托方和受托方签署">授权委托书</option>
<option value="quote-confirmation" data-title="报价确认单" data-name="报价确认单" data-code="TPL-QUOTE-CONFIRMATION-V1" data-file="报价确认单(报价版本快照).pdf" data-description="绑定已审核报价版本;快递方单方签署">报价确认单</option>
</select>
</div>
<div class="agreement-template-note" role="status">
<span class="material-icons-outlined" aria-hidden="true">description</span>
<div><strong><span data-template-name>收款账户证明</span> <span data-template-code>TPL-ACCOUNT-CERT-V2</span></strong><p data-template-description>原文件:收款账户证明文件.doc;对方企业盖章或个人签字</p></div>
</div>
<div class="agreement-field">
<div class="agreement-field-label-row">
<label for="agreement-signing-subject">我方签署主体 <span class="agreement-required" aria-hidden="true">*</span></label>
<button class="agreement-inline-button" type="button" data-subject-manage-open>
<span class="material-icons-outlined" aria-hidden="true">business</span>
<span>管理主体</span>
</button>
</div>
<select class="agreement-control" id="agreement-signing-subject" name="signing_subject" data-signing-subject-select required>
@forelse ($agreementSubjects as $subject)
<option value="{{ $subject->name }}" data-subject-id="{{ $subject->id }}" @selected($subject->is_default || (!$agreementDefaultSubject && $loop->first))>{{ $subject->name }}{{ $subject->is_default ? '(默认)' : '' }}</option>
@empty
<option value="{{ $agreementCompanyName }}" data-subject-fallback="true">{{ $agreementCompanyName }}(当前公司)</option>
@endforelse
</select>
<p class="agreement-help">从主体档案选择本次签署主体;公司全称仍可按本份文件单独调整。</p>
</div>
<div class="agreement-field">
<label for="agreement-company-name">公司全称 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-company-name" name="company_full_name" type="text" value="{{ $agreementCompanyName }}" data-company-name data-subject-linked-name autocomplete="organization" required>
</div>
<div class="agreement-field">
<label for="agreement-deadline">签署截止日期 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-deadline" name="signing_deadline" type="date" min="{{ now()->toDateString() }}" value="{{ now()->addDays(7)->toDateString() }}" required>
</div>
<div class="agreement-field">
<label for="agreement-signature-date">签署日期 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-signature-date" name="signature_date" type="date" value="{{ old('signature_date', now()->toDateString()) }}" required>
<p class="agreement-help">该日期会直接写入待签文件,并随原文一起推送到 E 签宝。</p>
</div>
<div class="agreement-field">
<label for="agreement-esign-account"><span data-primary-esign-label>对方 E 签宝账号</span></label>
<input class="agreement-control" id="agreement-esign-account" name="esign_account" type="text" value="" data-esign-account placeholder="手机号或邮箱" autocomplete="email" required>
<p class="agreement-help" data-partner-account-help>选择快递公司后自动带出工作平台的“电子签章经办人”(dzqzjbr);如资料未维护,可手工填写对方在 E 签宝实名绑定的手机号或邮箱。</p>
</div>
<div class="agreement-field agreement-field--full" data-account-signer-type-field>
<span class="agreement-field-label" data-account-signer-type-label>对方签署主体类型 <span class="agreement-required" aria-hidden="true">*</span></span>
<div class="agreement-archive-options">
<label class="agreement-archive-choice"><input type="radio" name="counterparty_signer_type" value="organization" checked data-account-signer-type><span><strong data-signer-type-organization-title>企业签署</strong><span data-signer-type-organization-help>填写 E 签宝认证的企业全称和经办人姓名</span></span></label>
<label class="agreement-archive-choice"><input type="radio" name="counterparty_signer_type" value="person" data-account-signer-type><span><strong data-signer-type-person-title>个人签署</strong><span data-signer-type-person-help>填写 E 签宝实名认证的个人姓名,不需要企业全称</span></span></label>
</div>
</div>
<div class="agreement-field" data-account-organization-field>
<label for="agreement-counterparty-organization"><span data-account-signer-label>对方签署企业全称</span> <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-counterparty-organization" name="counterparty_organization_name" type="text" placeholder="填写对方在 E 签宝认证的企业全称" autocomplete="organization" data-account-organization-name required>
<p class="agreement-help" data-account-signer-help>必须与对方 E 签宝企业认证名称一致;这是签署主体,不要求与银行卡持卡人姓名一致。</p>
</div>
<div class="agreement-field" data-primary-operator-field>
<label for="agreement-operator-name"><span data-primary-operator-label>对方 E 签宝实名认证姓名</span> <span class="agreement-required" data-account-operator-required aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-operator-name" name="operator_name" type="text" placeholder="填写与 E 签宝账号匹配的实名姓名" autocomplete="name" data-account-operator-name required>
<p class="agreement-help" data-account-operator-help>仅用于 E 签宝身份核验,不是收款人姓名;收款人姓名请填写在下方账户资料中。</p>
</div>
<div class="agreement-field" data-quote-confirmation-field hidden>
<label for="agreement-quote-version">报价版本 <span class="agreement-required" aria-hidden="true">*</span></label>
<select class="agreement-control" id="agreement-quote-version" name="quote_version_id" data-quote-version disabled required>
<option value="">请选择已审核报价版本</option>
@foreach ($agreementQuoteVersions as $quoteVersion)
<option value="{{ $quoteVersion->id }}" data-carrier="{{ $quoteVersion->carrier_name }}" data-quote-type="{{ $quoteVersion->quote_type }}" data-effective-date="{{ $quoteVersion->effective_date?->toDateString() }}" data-preview-url="{{ route('business.courier-agreement-signatures.quotes.preview', $quoteVersion) }}">
{{ $quoteVersion->version_code }} · {{ $quoteVersion->carrier_name }} · {{ $quoteVersion->quote_type }} · {{ $quoteVersion->effective_date?->toDateString() }}
</option>
@endforeach
</select>
<p class="agreement-help">确认单绑定已审核报价版本,生成后保存该版本快照;变价请生成新版本并重新签署。</p>
</div>
<div class="agreement-field" data-secondary-signer-fields hidden>
<label for="agreement-secondary-esign-account"><span data-secondary-esign-label>第二签署方 E 签宝账号</span> <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-secondary-esign-account" name="secondary_esign_account" type="text" placeholder="填写另一签署方的手机号或邮箱" autocomplete="email" disabled>
<p class="agreement-help">主体变更、合作合同和授权委托书需要双方分别实名签署;快递合作合同使用我方账号 {{ $agreementCooperationSecondaryEsignAccount }},供应商合作合同请填写我方签署账号。</p>
</div>
<div class="agreement-field" data-secondary-operator-field hidden>
<label for="agreement-secondary-operator-name"><span data-secondary-operator-label>变更后主体 E 签宝实名认证姓名</span> <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-secondary-operator-name" name="secondary_operator_name" type="text" placeholder="填写变更后主体签署人的实名姓名" autocomplete="name" disabled>
<p class="agreement-help">必须与第二签署方 E 签宝账号绑定的实名认证姓名一致,不能填写公司名称。</p>
</div>
</div>
</section>
<section class="agreement-form-section" aria-labelledby="agreement-variables-heading">
<h3 class="agreement-section-heading" id="agreement-variables-heading"><span data-variable-template-name>收款账户证明</span> <span data-variable-template-status>— 填写变量</span></h3>
<div class="agreement-form-grid" data-template-fields="account-proof">
<div class="agreement-field">
<label for="agreement-proof-effective-date">生效日期 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-proof-effective-date" name="account_proof_effective_date" type="date" value="{{ now()->toDateString() }}" required>
</div>
<div class="agreement-field">
<label for="agreement-proof-account-name">开户名称(持卡人姓名) <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-proof-account-name" name="account_proof_account_name" type="text" placeholder="填写持卡人姓名" autocomplete="name" required>
<p class="agreement-help">填写实际收款银行卡对应的持卡人姓名,无需与营业执照或公司全称一致。</p>
</div>
<div class="agreement-field">
<label for="agreement-proof-bank-name">开户银行 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-proof-bank-name" name="account_proof_bank_name" type="text" placeholder="如:工商银行上海浦东支行" required>
</div>
<div class="agreement-field">
<label for="agreement-proof-bank-account">银行帐户 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-proof-bank-account" name="account_proof_bank_account" type="text" inputmode="numeric" autocomplete="off" required>
</div>
</div>
<div class="agreement-form-grid" data-template-fields="account-change" hidden>
<div class="agreement-field">
<label for="agreement-change-date">账户变更日期 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-change-date" name="account_change_date" type="date" value="{{ now()->toDateString() }}" required>
</div>
<div class="agreement-field">
<label for="agreement-old-account-name">原收款账户(持卡人姓名) <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-old-account-name" name="old_account_name" type="text" placeholder="填写原持卡人姓名" autocomplete="name" required>
<p class="agreement-help">填写原收款银行卡对应的持卡人姓名,无需与营业执照或公司全称一致。</p>
</div>
<div class="agreement-field">
<label for="agreement-old-account-number">原账号 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-old-account-number" name="old_account_number" type="text" inputmode="numeric" autocomplete="off" required>
</div>
<div class="agreement-field">
<label for="agreement-old-stop-date">原账户停止使用日期 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-old-stop-date" name="old_account_stop_date" type="date" value="{{ now()->toDateString() }}" required>
</div>
<div class="agreement-field">
<label for="agreement-new-effective-date">新账户启用日期 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-new-effective-date" name="new_account_effective_date" type="date" value="{{ now()->toDateString() }}" required>
</div>
<div class="agreement-field">
<label for="agreement-new-account-name">新开户名称(持卡人姓名) <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-new-account-name" name="new_account_name" type="text" placeholder="填写新持卡人姓名" autocomplete="name" required>
<p class="agreement-help">填写新收款银行卡对应的持卡人姓名,无需与营业执照或公司全称一致。</p>
</div>
<div class="agreement-field">
<label for="agreement-new-bank-name">新开户银行 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-new-bank-name" name="new_bank_name" type="text" required>
</div>
<div class="agreement-field">
<label for="agreement-new-bank-account">新银行账户 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-new-bank-account" name="new_bank_account" type="text" inputmode="numeric" autocomplete="off" required>
</div>
</div>
<div class="agreement-form-grid" data-template-fields="entity-change" hidden>
<div class="agreement-field agreement-field--full">
<label class="agreement-checkbox-choice"><input type="checkbox" name="entity_change_old_company_deregistered" value="1" data-entity-change-deregistered><span><strong>变更前公司已注销,使用原法人个人签署</strong><span>原法人以个人身份签字,变更后公司仍须法人签字并盖章。</span></span></label>
</div>
<div class="agreement-field">
<label for="agreement-former-company">变更前公司名称 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-former-company" name="former_company_name" type="text" required>
</div>
<div class="agreement-field">
<label for="agreement-entity-change-date">企业名称变更日期 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-entity-change-date" name="entity_change_date" type="date" value="{{ now()->toDateString() }}" required>
</div>
<div class="agreement-field">
<label for="agreement-changed-company">变更后公司名称 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-changed-company" name="changed_company_name" type="text" required>
</div>
<div class="agreement-field">
<label for="agreement-changed-company-start-date">新公司启用日期 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-changed-company-start-date" name="changed_company_start_date" type="date" value="{{ now()->toDateString() }}" required>
</div>
</div>
<div class="agreement-form-grid" data-template-fields="shared-contract" hidden>
<div class="agreement-field">
<label for="agreement-contract-partner"><span data-shared-subject-label>物流商归属主体(企业全称)</span> <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-contract-partner" name="contract_partner_name" type="text" placeholder="填写物流商归属企业在 E 签宝认证的全称" autocomplete="organization" required>
<p class="agreement-help" data-shared-subject-help>由该企业盖章确认快递归属及结算主体;正文合作方使用上方的我方公司全称。</p>
</div>
<div class="agreement-field agreement-field--full">
<label>共用合同物流商(快递名称,可多个) <span class="agreement-required" aria-hidden="true">*</span></label>
<div class="agreement-shared-courier-list" data-shared-courier-list>
<div class="agreement-shared-courier-row">
<input class="agreement-control" name="shared_courier_names[]" type="text" placeholder="第1家快递公司名称" data-shared-courier required>
<button class="agreement-icon-button" type="button" data-shared-courier-remove disabled title="删除共用公司" aria-label="删除共用公司"><span class="material-icons-outlined" aria-hidden="true">delete</span></button>
</div>
</div>
<button class="agreement-inline-button agreement-shared-courier-add" type="button" data-shared-courier-add>
<span class="material-icons-outlined" aria-hidden="true">add</span>
<span>添加共用公司</span>
</button>
<p class="agreement-help">填写归属上述企业或个人、共用合同和打款资料的快递名称,可添加多个。</p>
</div>
<div class="agreement-field agreement-field--full">
<label for="agreement-shared-note">备注</label>
<textarea class="agreement-control" id="agreement-shared-note" name="shared_note" placeholder="如:请在3个工作日内完成签章,如有疑问请联系张晓华 138-xxxx-xxxx" data-shared-note></textarea>
</div>
</div>
<div class="agreement-form-grid" data-template-fields="cooperation-contract" hidden>
<div class="agreement-field">
<label for="agreement-cooperation-party-a-name">甲方名称 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-cooperation-party-a-name" name="cooperation_party_a_name" type="text" value="{{ $agreementCompanyName }}" data-subject-linked-name required>
</div>
<div class="agreement-field">
<label for="agreement-cooperation-party-a-phone">甲方电话 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-cooperation-party-a-phone" name="cooperation_party_a_phone" type="tel" value="{{ setting('company.phone') }}" autocomplete="tel" required>
</div>
<div class="agreement-field">
<label for="agreement-cooperation-party-b-name"><span data-cooperation-party-b-label>乙方名称</span> <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-cooperation-party-b-name" name="cooperation_party_b_name" type="text" placeholder="快递公司完整签署名称" required>
</div>
<div class="agreement-field">
<label for="agreement-cooperation-party-b-phone">乙方电话 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-cooperation-party-b-phone" name="cooperation_party_b_phone" type="tel" autocomplete="tel" required>
</div>
<div class="agreement-field">
<label for="agreement-cooperation-start-date">协议开始日期 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-cooperation-start-date" name="cooperation_start_date" type="date" value="{{ now()->toDateString() }}" required>
</div>
<div class="agreement-field">
<label for="agreement-cooperation-end-date">协议结束日期 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-cooperation-end-date" name="cooperation_end_date" type="date" value="{{ now()->addYear()->toDateString() }}" required>
</div>
<div class="agreement-field" data-courier-contract-metadata>
<label for="agreement-cooperation-contract-number">合同编号(选填)</label>
<input class="agreement-control" id="agreement-cooperation-contract-number" name="cooperation_contract_number" type="text" maxlength="100" placeholder="填写正式合同编号,不填写则合同管理显示未填写">
</div>
<div class="agreement-field" data-courier-contract-metadata data-courier-contract-legal>
<label for="agreement-cooperation-party-b-legal">乙方法定代表人(选填)</label>
<input class="agreement-control" id="agreement-cooperation-party-b-legal" name="cooperation_party_b_legal_representative" type="text" maxlength="100" placeholder="以营业执照为准,不是签章经办人">
<p class="agreement-help">用于合同管理登记;不会替代 E 签宝实名认证姓名。个人签署不适用。</p>
</div>
</div>
<div data-supplier-contract-fields hidden>
<div class="agreement-field">
<label for="agreement-supplier-contract-template">合同模板 <span class="agreement-required" aria-hidden="true">*</span></label>
<select class="agreement-control" id="agreement-supplier-contract-template" name="supplier_contract_template" data-supplier-contract-template disabled required>
@foreach ($supplierContractTemplates as $key => $template)
<option value="{{ $key }}" data-name="{{ $template['name'] }}" data-code="{{ $template['code'] }}" data-file="{{ $template['file'] }}">{{ $template['name'] }} · V{{ $template['version'] }}</option>
@endforeach
</select>
<p class="agreement-help">正文和附件按所选模板一起签署,签署任务保留本次模板版本。</p>
</div>
<div class="agreement-form-grid">
@foreach (\App\Support\SupplierCooperationTemplates::FIELDS as $key => $field)
<div class="agreement-field" data-supplier-field-templates="{{ implode(' ', $field['templates'] ?? array_keys($supplierContractTemplates)) }}">
<label for="supplier-contract-{{ $key }}">{{ $field['label'] }} @if($field['required'] ?? false)<span class="agreement-required" aria-hidden="true">*</span>@endif</label>
<input class="agreement-control" id="supplier-contract-{{ $key }}" name="supplier_contract_fields[{{ $key }}]" data-supplier-field="{{ $key }}" type="{{ $field['type'] ?? 'text' }}" value="{{ $key === 'number' ? 'SUP-' . strtoupper(substr(str_replace('-', '', $supplierContractRequestKey), 0, 12)) : ($field['default'] ?? '') }}" maxlength="{{ $key === 'supply_price' ? 1000 : 255 }}" @required($field['required'] ?? false) disabled>
</div>
@endforeach
</div>
<p class="agreement-help">按原合同填写银行账户资料;其余空白项可按本次合作情况补充,发送前请查看完整正文及附件。</p>
</div>
<div data-template-fields="authorization" hidden>
<div class="agreement-form-grid">
<div class="agreement-field agreement-field--full">
<span class="agreement-field-label">受托方签署类型 <span class="agreement-required" aria-hidden="true">*</span></span>
<div class="agreement-archive-options">
<label class="agreement-archive-choice"><input type="radio" name="secondary_signer_type" value="organization" checked data-authorization-secondary-signer-type><span><strong>企业签署</strong><span>填写企业名称及其经办人的 E 签宝实名姓名</span></span></label>
<label class="agreement-archive-choice"><input type="radio" name="secondary_signer_type" value="person" data-authorization-secondary-signer-type><span><strong>个人签署</strong><span>受托方姓名须与 E 签宝账号实名认证一致</span></span></label>
</div>
</div>
</div>
<div class="agreement-form-grid">
<div class="agreement-field">
<label for="agreement-principal-name"><span data-principal-name-label>委托方(个人或公司)</span> <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-principal-name" name="principal_name" type="text" required>
</div>
<div class="agreement-field">
<label for="agreement-principal-id">委托方身份证号/营业执照号 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-principal-id" name="principal_id_number" type="text" autocomplete="off" required>
</div>
<div class="agreement-field">
<label for="agreement-trustee-name"><span data-trustee-name-label>受托方(个人或公司)</span> <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-trustee-name" name="trustee_name" type="text" required>
</div>
<div class="agreement-field">
<label for="agreement-trustee-id">受托方身份证号/营业执照号 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-trustee-id" name="trustee_id_number" type="text" autocomplete="off" required>
</div>
</div>
<fieldset class="agreement-form-section" aria-required="true">
<legend class="agreement-section-heading">授权事项(可多选) <span class="agreement-required" aria-hidden="true">*</span></legend>
<div class="agreement-checkbox-grid">
<label class="agreement-checkbox-choice"><input type="checkbox" name="authorization_items[]" value="1" data-authorization-item><span>1、代签往来业务每月账单</span></label>
<label class="agreement-checkbox-choice"><input type="checkbox" name="authorization_items[]" value="2" data-authorization-item><span>2、代签借支协议</span></label>
<label class="agreement-checkbox-choice"><input type="checkbox" name="authorization_items[]" value="3" data-authorization-item><span>3、代签汇款账号变更</span></label>
<label class="agreement-checkbox-choice"><input type="checkbox" name="authorization_items[]" value="4" data-authorization-item><span>4、代收往来货款</span></label>
</div>
</fieldset>
<div class="agreement-form-grid">
<div class="agreement-field">
<label for="agreement-bill-counterparty">账单往来方 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-bill-counterparty" name="bill_counterparty" type="text" value="{{ $agreementCompanyName }}" data-subject-linked-name required>
</div>
<div class="agreement-field">
<label for="agreement-loan-counterparty">借支协议相对方 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-loan-counterparty" name="loan_counterparty" type="text" value="{{ $agreementCompanyName }}" data-subject-linked-name required>
</div>
<div class="agreement-field">
<label for="agreement-payment-counterparty">代收货款往来方 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-payment-counterparty" name="payment_counterparty" type="text" value="{{ $agreementCompanyName }}" data-subject-linked-name required>
</div>
<div class="agreement-field">
<label for="agreement-authorization-start">委托有效期开始 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-authorization-start" name="authorization_start_date" type="date" value="{{ now()->toDateString() }}" required>
</div>
<div class="agreement-field">
<label for="agreement-authorization-end">委托有效期结束 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-authorization-end" name="authorization_end_date" type="date" value="{{ now()->addYear()->toDateString() }}" required>
</div>
</div>
</div>
</section>
@include('business.pages.courier-payables.credential-upload')
<fieldset class="agreement-form-section agreement-archive-fieldset" data-archive-fieldset>
<legend class="agreement-section-heading">回传归档</legend>
<div class="agreement-archive-options">
<label class="agreement-archive-choice"><input type="radio" name="archive_mode" value="auto" checked><span><strong>签署完成后自动归档</strong><span>回传文件直接存入档案中心</span></span></label>
<label class="agreement-archive-choice"><input type="radio" name="archive_mode" value="manual"><span><strong>人工确认后归档</strong><span>回传后需财务确认内容再归档</span></span></label>
</div>
</fieldset>
<p class="agreement-form-error" role="alert" data-request-error></p>
</div>
<footer class="agreement-request-actions">
<button class="agreement-button" type="button" data-request-cancel><span class="material-icons-outlined" aria-hidden="true">close</span><span>取消</span></button>
<button class="agreement-button" type="button" data-preview-refresh><span class="material-icons-outlined" aria-hidden="true">refresh</span><span>刷新预览</span></button>
<button class="agreement-button agreement-button--primary" type="submit" data-sign-request-send {{ $esignConfigured ? '' : 'disabled' }} title="{{ $esignConfigured ? '推送至E签宝' : 'E签宝沙箱应用尚未配置' }}"><span class="material-icons-outlined" aria-hidden="true">send</span><span>推送至E签宝</span></button>
</footer>
</form>
<aside class="agreement-preview-pane" aria-label="协议实时预览" data-agreement-preview>
<header class="agreement-preview-header">
<h2 class="agreement-preview-title"><span class="material-icons-outlined" aria-hidden="true">preview</span><span>文件预览</span></h2>
<span class="agreement-preview-meta"><span data-preview-template-code>TPL-ACCOUNT-CERT-V2</span> · <span data-preview-status-hint>蓝色=已填 红色=待填</span></span>
</header>
<div class="agreement-preview-scroll">
<div data-credential-preview hidden></div>
<article class="agreement-preview-paper" data-template-preview="account-proof">
<h3>收款帐户资料证明</h3>
<p>TO <strong data-preview-bind="company">{{ $agreementCompanyName }}</strong>:</p>
<p>基于我公司正规化管理的需要,同时保证广大客户的汇款安全,我司同意自 <span class="agreement-preview-value" data-preview-bind="proofEffectiveDate">{{ now()->format('Y年n月j日') }}</span> 起我司货款(运费),请汇款至以下账户:</p>
<div class="agreement-preview-account">
<div><span>开户名称:</span><span class="agreement-preview-value" data-preview-bind="proofAccountName">待填写</span></div>
<div><span>开户银行:</span><span class="agreement-preview-value" data-preview-bind="proofBankName">待填写</span></div>
<div><span>银行帐户:</span><span class="agreement-preview-value" data-preview-bind="proofBankAccount">待填写</span></div>
</div>
<p>请贵公司按照上述汇款资料付款,如因我司提供收款银行帐户资料错误,导致相关款项支付不到位,则由此产生的一切经济纠纷和责任由我司承担。我司承诺若上述收款银行帐户资料发生变化及时书面通知贵公司。给贵公司带来的不便尽请谅解。</p>
<p>以上收款账户的变更,以我司的盖章为有效。</p>
<div class="agreement-preview-signature">
<p><span data-preview-bind="proofSigner">待填写</span>:</p>
<div class="agreement-preview-signature-blank"></div>
<p>日期:<span data-preview-bind="signatureDate">{{ now()->format('Y年n月j日') }}</span></p>
</div>
<p class="agreement-preview-page-number">第 1 页 / 共 1 页</p>
</article>
<article class="agreement-preview-paper" data-template-preview="account-change" hidden>
<h3>收款帐户资料变更证明</h3>
<p>TO <strong data-preview-bind="company">{{ $agreementCompanyName }}</strong>:</p>
<p>基于我公司正规化管理的需要,同时保证广大客户的汇款安全,我司收款账户将于 <span class="agreement-preview-value" data-preview-bind="accountChangeDate">待填写</span> 变更账户,之前相应的账户(收款账户为:<span class="agreement-preview-value" data-preview-bind="oldAccountName">待填写</span>,账号:<span class="agreement-preview-value" data-preview-bind="oldAccountNumber">待填写</span>)于 <span class="agreement-preview-value" data-preview-bind="oldAccountStopDate">待填写</span> 停止使用,即日起我司收款的银行帐户进行变更,自 <span class="agreement-preview-value" data-preview-bind="newAccountEffectiveDate">待填写</span> 起我司与贵司往来款项请汇款至以下新账户,新汇款资料如下:</p>
<div class="agreement-preview-account">
<div><span>开户名称:</span><span class="agreement-preview-value" data-preview-bind="newAccountName">待填写</span></div>
<div><span>开户银行:</span><span class="agreement-preview-value" data-preview-bind="newBankName">待填写</span></div>
<div><span>银行账户:</span><span class="agreement-preview-value" data-preview-bind="newBankAccount">待填写</span></div>
</div>
<p>请贵公司按照上述汇款资料付款,如因我司提供收款银行帐户资料错误,导致相关款项支付不到位,则由此产生的一切经济纠纷和责任由我司承担。我司承诺若上述收款银行帐户资料发生变化及时书面通知贵公司。给贵公司带来的不便尽请谅解。</p>
<p>以上收款账户的变更,以我司的盖章为有效。</p>
<div class="agreement-preview-signature">
<p><span data-preview-bind="changeSigner">待填写</span>:</p>
<div class="agreement-preview-signature-blank"></div>
<p>日期:<span data-preview-bind="signatureDate">{{ now()->format('Y年n月j日') }}</span></p>
</div>
<p class="agreement-preview-page-number">第 1 页 / 共 1 页</p>
</article>
<article class="agreement-preview-paper" data-template-preview="entity-change" hidden>
<h3>公司主体变更证明</h3>
<p>致 <strong data-preview-bind="company">{{ $agreementCompanyName }}</strong>:</p>
<p data-entity-organization-description>我司由于企业名称变更,原公司名称 <span class="agreement-preview-value" data-preview-bind="formerCompanyName">待填写</span> 于 <span class="agreement-preview-value" data-preview-bind="entityChangeDate">待填写</span> 变更为 <span class="agreement-preview-value" data-preview-bind="changedCompanyName">待填写</span>,自 <span class="agreement-preview-value" data-preview-bind="changedCompanyStartDate">待填写</span> 开始,我司将启用变更后的公司与贵公司开展工作,原公司名称停止使用。</p>
<p data-entity-person-description hidden>原合作主体 <span class="agreement-preview-value" data-preview-bind="formerCompanyName">待填写</span> 已注销,由原公司法人 <span class="agreement-preview-value" data-preview-bind="formerLegalRepresentative">待填写</span> 以个人身份确认本证明。自 <span class="agreement-preview-value" data-preview-bind="changedCompanyStartDate">待填写</span> 起,改由 <span class="agreement-preview-value" data-preview-bind="changedCompanyName">待填写</span> 与贵公司开展业务。</p>
<p>变更后,原公司的各项事宜由变更后的公司继续执行。原公司的结算未付款项,由变更之后的公司提供的收款账户收款。原公司的业务和款项若出现法律上的纠纷,由变更后的公司承担责任。</p>
<p>特此证明!</p>
<div class="agreement-preview-signature agreement-preview-signature--split">
<div class="agreement-preview-signature-slot">
<p data-entity-organization-signatures>变更前公司法人签字盖公章:<span class="agreement-preview-value" data-preview-bind="formerCompanyName">待填写</span></p>
<p data-entity-organization-signatures>签署人:<span class="agreement-preview-value" data-preview-bind="formerLegalRepresentative">待填写</span></p>
<p data-entity-person-signature hidden>原公司法人个人签字:<span class="agreement-preview-value" data-preview-bind="formerLegalRepresentative">待填写</span></p>
<div class="agreement-preview-signature-blank"></div>
<div data-entity-organization-signatures>
<p>法人签字:</p>
<div class="agreement-preview-handwriting-blank"></div>
</div>
<p>日期:<span data-preview-bind="signatureDate">{{ now()->format('Y年n月j日') }}</span></p>
</div>
<div class="agreement-preview-signature-slot">
<p>变更后公司法人签字盖公章:<span class="agreement-preview-value" data-preview-bind="changedCompanyName">待填写</span>(签署人:<span class="agreement-preview-value" data-preview-bind="changedLegalRepresentative">待填写</span>)</p>
<div class="agreement-preview-signature-blank"></div>
<p>法人签字:</p>
<div class="agreement-preview-handwriting-blank"></div>
<p>日期:<span data-preview-bind="signatureDate">{{ now()->format('Y年n月j日') }}</span></p>
</div>
</div>
<p class="agreement-preview-page-number">第 1 页 / 共 1 页</p>
</article>
<article class="agreement-preview-paper" data-template-preview="shared-contract" hidden>
<h3>证明</h3>
<p>与 <span class="agreement-preview-value" data-preview-bind="company">{{ $agreementCompanyName }}</span> 合作的 <span class="agreement-preview-value" data-preview-bind="sharedCourierName">待填写</span>,均归属于 <span class="agreement-preview-value" data-preview-bind="contractPartnerName">待填写</span>,共用一份合同及同一份打款资料,合同签署及结算主体均为 <span class="agreement-preview-value" data-preview-bind="contractPartnerName">待填写</span>。</p>
<p>特此证明!</p>
<p data-preview-shared-note hidden>备注:<span class="agreement-preview-value" data-preview-bind="sharedNote">待填写</span></p>
<div class="agreement-preview-signature">
<p><span data-preview-bind="sharedSignerLabel">确认企业</span>:<span class="agreement-preview-value" data-preview-bind="contractPartnerName">待填写</span></p>
<p data-shared-organization-signature>法人签字并公司盖章:</p>
<div class="agreement-preview-signature-blank"></div>
<p>日期:<span data-preview-bind="signatureDate">{{ now()->format('Y年n月j日') }}</span></p>
</div>
<p class="agreement-preview-page-number">第 1 页 / 共 1 页</p>
</article>
<article class="agreement-preview-paper" data-template-preview="cooperation-contract" hidden>
<h3>服务协议</h3>
@include('business.partials.cooperation-contract', ['mode' => 'preview', 'payload' => []])
<p class="agreement-preview-page-number">原合同全文预览</p>
</article>
<article class="agreement-preview-paper" data-template-preview="supplier-cooperation" hidden>
@foreach ($supplierContractTemplates as $key => $template)
<div data-supplier-contract-preview="{{ $key }}" @if(!$loop->first) hidden @endif>
@include('business.partials.supplier-cooperation-contract', ['templateKey' => $key, 'mode' => 'preview', 'payload' => []])
</div>
@endforeach
</article>
<article class="agreement-preview-paper" data-template-preview="authorization" hidden>
<h3>授权委托书</h3>
<div class="agreement-preview-account">
<div><span>委托方:</span><span class="agreement-preview-value" data-preview-bind="principalName">待填写</span></div>
<div><span>身份证号/营业执照号:</span><span class="agreement-preview-value" data-preview-bind="principalIdNumber">待填写</span></div>
<div><span>受托方:</span><span class="agreement-preview-value" data-preview-bind="trusteeName">待填写</span></div>
<div><span>身份证号/营业执照号:</span><span class="agreement-preview-value" data-preview-bind="trusteeIdNumber">待填写</span></div>
</div>
<p>兹委托 <span class="agreement-preview-value" data-preview-bind="trusteeName">待填写</span> 为我或我司的代理人,全权代表我或我司办理下列第 <span class="agreement-preview-value" data-preview-bind="authorizationItemNumbers">待选择</span> 条事项(可多选)。</p>
<ol class="agreement-preview-list">
<li>代表委托方代签与 <span class="agreement-preview-value" data-preview-bind="billCounterparty">待填写</span> 的往来业务每月的账单(双方确认的账单金额)</li>
<li>代表委托方代签与 <span class="agreement-preview-value" data-preview-bind="loanCounterparty">待填写</span> 借支协议的事项</li>
<li>代表委托方代签汇款账号变更的事项</li>
<li>代表委托方代收 <span class="agreement-preview-value" data-preview-bind="paymentCounterparty">待填写</span> 的往来货款</li>
</ol>
<p>委托代签以上事项时效性,以委托书上签的有效期为准,委托有效期:从 <span class="agreement-preview-value" data-preview-bind="authorizationStartDate">待填写</span> 至 <span class="agreement-preview-value" data-preview-bind="authorizationEndDate">待填写</span> 止。</p>
<div class="agreement-preview-signature agreement-preview-signature--split">
<div class="agreement-preview-signature-slot">
<p>委托方:<span data-preview-bind="principalName">待填写</span></p>
<div class="agreement-preview-signature-blank"></div>
<p>签字:</p>
<div class="agreement-preview-handwriting-blank"></div>
<p>日期:<span data-preview-bind="signatureDate">{{ now()->format('Y年n月j日') }}</span></p>
</div>
<div class="agreement-preview-signature-slot">
<p>受托方:<span data-preview-bind="trusteeName">待填写</span></p>
<div class="agreement-preview-signature-blank"></div>
<p>签字:</p>
<div class="agreement-preview-handwriting-blank"></div>
<p>日期:<span data-preview-bind="signatureDate">{{ now()->format('Y年n月j日') }}</span></p>
</div>
</div>
<p class="agreement-preview-page-number">第 1 页 / 共 1 页</p>
</article>
<article class="agreement-preview-paper" data-template-preview="quote-confirmation" hidden>
<h3>报价确认单</h3>
<div class="agreement-preview-account">
<div><span>报价版本:</span><span class="agreement-preview-value" data-preview-bind="quoteVersion">待选择</span></div>
<div><span>快递公司:</span><span class="agreement-preview-value" data-preview-bind="quoteCarrier">待选择</span></div>
<div><span>报价类型:</span><span class="agreement-preview-value" data-preview-bind="quoteType">待选择</span></div>
<div><span>甲方:</span><span class="agreement-preview-value" data-preview-bind="quotePartyA">{{ $agreementCompanyName }}</span></div>
<div><span>乙方:</span><span class="agreement-preview-value" data-preview-bind="quotePartyB">待选择</span></div>
<div><span>生效日期:</span><span class="agreement-preview-value" data-preview-bind="quoteEffectiveDate">待选择</span></div>
<div><span>失效日期:</span><span class="agreement-preview-value" data-preview-bind="quoteExpiryDate">按下一版本确定</span></div>
<div><span>面单费:</span><span class="agreement-preview-value" data-preview-bind="quoteFaceFee">按报价版本</span></div>
<div><span>计泡系数:</span><span class="agreement-preview-value" data-preview-bind="quoteBubbleCoefficient">按报价版本</span></div>
</div>
<p>双方确认以下报价版本作为快递服务结算依据。报价版本一经签署即形成独立留档,后续变价须生成新版本并重新签署。</p>
<div class="agreement-preview-quote-matrix" data-preview-bind="quoteMatrix">请选择报价版本后查看报价明细</div>
<div class="agreement-preview-signature"><p>乙方(快递方)签章:</p><div class="agreement-preview-signature-blank"></div><p>日期:<span data-preview-bind="signatureDate">{{ now()->format('Y年n月j日') }}</span></p></div>
<p class="agreement-preview-page-number">报价确认单 · 快递方单方签署</p>
</article>
</div>
</aside>
</div>
</section>
<section class="agreement-panel" id="agreement-panel-templates" role="tabpanel" aria-labelledby="agreement-tab-templates" data-agreement-panel="templates" hidden>
<div class="agreement-template-summary">
<div class="agreement-template-summary__copy">
<strong>协议模板清单</strong>
<p>已按原始协议文件和报价版本快照分别映射字段、正文和签署角色;报价确认单只由快递方签署。</p>
</div>
<span class="agreement-status agreement-status--warning">7种文件类型已映射</span>
</div>
<div class="agreement-table-wrap">
<table class="agreement-table agreement-template-table">
<thead>
<tr>
<th scope="col">业务场景</th>
<th scope="col">源文件</th>
<th scope="col">模板版本</th>
<th scope="col">字段映射</th>
<th scope="col">签署角色</th>
<th scope="col">签章位置</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
<tr><td>收款账户变更</td><td>收款账户变更证明.doc</td><td>本地映射 V1</td><td>变更日期、旧账户、停用日期、新账户、生效日期</td><td>快递公司</td><td><span class="agreement-status agreement-status--warning">公司盖章</span></td><td><button class="agreement-icon-button" type="button" disabled title="E签宝模板尚未创建"><span class="material-icons-outlined" aria-hidden="true">settings</span></button></td></tr>
<tr><td>收款账户证明</td><td>收款账户证明文件.doc</td><td>本地映射 V1</td><td>生效日期、开户名称、开户银行、银行帐户</td><td>快递公司</td><td><span class="agreement-status agreement-status--warning">公司盖章</span></td><td><button class="agreement-icon-button" type="button" disabled title="E签宝模板尚未创建"><span class="material-icons-outlined" aria-hidden="true">settings</span></button></td></tr>
<tr><td>公司主体变更</td><td>公司主体变更证明.docx</td><td>本地映射 V1</td><td>变更前后名称、变更日期、启用日期</td><td>变更前、变更后公司</td><td><span class="agreement-status agreement-status--warning">法人签字并盖章</span></td><td><button class="agreement-icon-button" type="button" disabled title="E签宝模板尚未创建"><span class="material-icons-outlined" aria-hidden="true">settings</span></button></td></tr>
<tr><td>共用合同证明</td><td>共用合同证明.docx</td><td>本地映射 V1</td><td>我方合作公司、物流商归属主体、共用合同快递、证明日期</td><td>物流商归属企业或个人</td><td><span class="agreement-status agreement-status--warning">企业盖章或个人签字</span></td><td><button class="agreement-icon-button" type="button" disabled title="E签宝模板尚未创建"><span class="material-icons-outlined" aria-hidden="true">settings</span></button></td></tr>
<tr><td>合作合同</td><td>保丟不保损-合同发快递2024.8.doc</td><td>本地映射 V1</td><td>甲乙方名称、甲乙方电话、协议起止日期</td><td>甲方、乙方</td><td><span class="agreement-status agreement-status--warning">双方签字盖章</span></td><td><button class="agreement-icon-button" type="button" disabled title="E签宝模板尚未创建"><span class="material-icons-outlined" aria-hidden="true">settings</span></button></td></tr>
@foreach ($supplierContractTemplates as $template)
<tr><td>{{ $template['name'] }}</td><td>{{ $template['file'] }}</td><td>V{{ $template['version'] }}</td><td>甲乙方资料、编号、日期、账户及附件变量</td><td>我方、供应商</td><td><span class="agreement-status agreement-status--warning">双方签署 · 含{{ $template['attachments'] }}项附件</span></td><td><span class="agreement-help">发起签章时选择</span></td></tr>
@endforeach
<tr><td>授权委托书</td><td>授权委托书(快递).docx</td><td>本地映射 V1</td><td>委托双方、授权事项、往来方、有效期</td><td>委托方、受托方</td><td><span class="agreement-status agreement-status--warning">双方签署</span></td><td><button class="agreement-icon-button" type="button" disabled title="E签宝模板尚未创建"><span class="material-icons-outlined" aria-hidden="true">settings</span></button></td></tr>
<tr><td>报价确认单</td><td>报价版本快照</td><td>本地映射 V1</td><td>版本号、快递公司、报价类型、有效期、报价明细</td><td>快递公司</td><td><span class="agreement-status agreement-status--warning">快递方签章</span></td><td><button class="agreement-icon-button" type="button" disabled title="E签宝模板尚未创建"><span class="material-icons-outlined" aria-hidden="true">settings</span></button></td></tr>
</tbody>
</table>
</div>
<div class="agreement-panel-footnote">
<span class="material-icons-outlined" aria-hidden="true">history</span>
<span>后续每次模板更新都应生成新版本;历史任务必须继续关联发起时的模板版本,不能被新版模板覆盖。</span>
</div>
</section>
<div class="agreement-modal" role="presentation" aria-hidden="true" data-subject-modal hidden>
<div class="agreement-modal__backdrop" data-subject-modal-close></div>
<section class="agreement-modal__dialog" role="dialog" aria-modal="true" aria-labelledby="agreement-subject-modal-title">
<header class="agreement-modal__header">
<h2 class="agreement-modal__title" id="agreement-subject-modal-title">
<span class="material-icons-outlined" aria-hidden="true">business</span>
<span>我方公司主体管理</span>
</h2>
<button class="agreement-modal-close" type="button" aria-label="关闭主体管理" data-subject-modal-close>
<span class="material-icons-outlined" aria-hidden="true">close</span>
</button>
</header>
<div class="agreement-modal__body">
<p class="agreement-modal__hint">
<span class="material-icons-outlined" aria-hidden="true">info</span>
<span>可维护多个公司主体,发起签章时按需选择。本次协议会保存发起时的主体名称快照。</span>
</p>
<div class="agreement-subject-list" data-subject-list aria-live="polite"></div>
<div data-subject-delete-panel hidden>
<p class="agreement-modal__hint"><span>确认删除公司主体“<strong data-subject-delete-name></strong>”?<span data-subject-delete-hint></span>历史协议的主体名称快照会保留。</span></p>
<p class="agreement-subject-form__error" role="alert" data-subject-delete-error></p>
<div class="agreement-subject-form__actions">
<button class="agreement-button" type="button" data-subject-delete-cancel>取消</button>
<button class="agreement-button agreement-button--danger" type="button" data-subject-delete-confirm>确认删除</button>
</div>
</div>
<form class="agreement-subject-form" method="POST" novalidate data-subject-form
data-store-url="{{ route('business.courier-agreement-signatures.subjects.store') }}"
data-update-url-template="{{ route('business.courier-agreement-signatures.subjects.update', ['subject' => '__subject__']) }}"
data-default-url-template="{{ route('business.courier-agreement-signatures.subjects.default', ['subject' => '__subject__']) }}"
data-delete-url-template="{{ route('business.courier-agreement-signatures.subjects.destroy', ['subject' => '__subject__']) }}">
@csrf
<input type="hidden" name="subject_id" data-subject-id>
<h3 class="agreement-subject-form__title" data-subject-form-title>新增公司主体</h3>
<div class="agreement-form-grid">
<div class="agreement-field">
<label for="agreement-subject-name">公司名称 <span class="agreement-required" aria-hidden="true">*</span></label>
<input class="agreement-control" id="agreement-subject-name" name="name" type="text" maxlength="255" placeholder="与营业执照一致" required data-subject-name>
</div>
<div class="agreement-field">
<label for="agreement-subject-code">统一社会信用代码</label>
<input class="agreement-control" id="agreement-subject-code" name="unified_social_credit_code" type="text" maxlength="18" placeholder="18位,选填" autocomplete="off" data-subject-code>
<p class="agreement-help">填写后用于核对签署主体,不会自动提交给 E 签宝。</p>
</div>
</div>
<p class="agreement-subject-form__error" role="alert" data-subject-form-error></p>
<div class="agreement-subject-form__actions">
<button class="agreement-button" type="button" data-subject-form-cancel hidden>取消编辑</button>
<button class="agreement-button agreement-button--primary" type="submit" data-subject-form-submit>
<span class="material-icons-outlined" aria-hidden="true">save</span>
<span>保存主体</span>
</button>
</div>
</form>
</div>
<footer class="agreement-modal__footer">
<button class="agreement-button" type="button" data-subject-modal-close>关闭</button>
</footer>
</section>
</div>
<div class="agreement-modal" role="presentation" aria-hidden="true" data-archive-modal hidden>
<div class="agreement-modal__backdrop" data-archive-modal-close></div>
<section class="agreement-modal__dialog agreement-archive-dialog" role="dialog" aria-modal="true" aria-labelledby="agreement-archive-modal-title">
<header class="agreement-modal__header">
<h2 class="agreement-modal__title" id="agreement-archive-modal-title"><span class="material-icons-outlined" aria-hidden="true">inventory_2</span>确认归档签署任务</h2>
<button class="agreement-modal-close" type="button" aria-label="关闭归档确认" data-archive-modal-close><span class="material-icons-outlined" aria-hidden="true">close</span></button>
</header>
<form class="agreement-modal__body" id="agreement-archive-confirm-form" data-archive-confirm-form>
<p class="agreement-modal__hint"><span class="material-icons-outlined" aria-hidden="true">info</span><span><strong data-archive-task-number></strong> 归档后将移入“已归档”,原文件、签署文件和完成证书仍可下载。</span></p>
<fieldset class="agreement-archive-fieldset">
<legend class="agreement-section-heading">归档原因 <span class="agreement-required" aria-hidden="true">*</span></legend>
<div class="agreement-archive-options">
<label class="agreement-archive-choice"><input type="radio" name="archive_reason_code" value="completed" checked required><span><strong>签署完成</strong><span>签署文件已核对</span></span></label>
<label class="agreement-archive-choice"><input type="radio" name="archive_reason_code" value="confirmed"><span><strong>财务已确认</strong><span>财务复核无误</span></span></label>
<label class="agreement-archive-choice"><input type="radio" name="archive_reason_code" value="backfill"><span><strong>历史补录</strong><span>补录以前的签署文件</span></span></label>
<label class="agreement-archive-choice"><input type="radio" name="archive_reason_code" value="other"><span><strong>其他</strong><span>请填写具体说明</span></span></label>
</div>
</fieldset>
<div class="agreement-field">
<label for="agreement-archive-note">归档说明</label>
<textarea class="agreement-control" id="agreement-archive-note" name="archive_note" rows="3" maxlength="200" placeholder="选择“其他”时必填,其他原因可选填" aria-describedby="agreement-archive-error"></textarea>
</div>
<p class="agreement-form-error" id="agreement-archive-error" role="alert" data-archive-error></p>
</form>
<footer class="agreement-modal__footer">
<button class="agreement-button" type="button" data-archive-modal-close>取消</button>
<button class="agreement-button agreement-button--primary" type="submit" form="agreement-archive-confirm-form" data-archive-confirm><span class="material-icons-outlined" aria-hidden="true">archive</span>确认归档</button>
</footer>
</section>
</div>
<div class="agreement-modal" role="presentation" aria-hidden="true" data-delete-task-modal hidden>
<div class="agreement-modal__backdrop" data-delete-task-close></div>
<section class="agreement-modal__dialog agreement-archive-dialog" role="dialog" aria-modal="true" aria-labelledby="agreement-delete-task-title" aria-describedby="agreement-delete-task-hint">
<header class="agreement-modal__header">
<h2 class="agreement-modal__title" id="agreement-delete-task-title"><span class="material-icons-outlined" aria-hidden="true">delete_outline</span>删除签署任务</h2>
<button class="agreement-modal-close" type="button" aria-label="关闭删除确认" data-delete-task-close><span class="material-icons-outlined" aria-hidden="true">close</span></button>
</header>
<div class="agreement-modal__body">
<strong data-delete-task-number></strong>
<p class="agreement-modal__hint" data-delete-task-description></p>
<p class="agreement-modal__hint" id="agreement-delete-task-hint">确认后,此任务将从本系统的全部列表移除。原文件和操作记录保留备查。</p>
<p class="agreement-modal__hint">删除本系统任务不会撤销或终止 E 签宝上的签署流程,已签署文件仍然有效。是否删除请自行核对。</p>
<p class="agreement-form-error" role="alert" data-delete-task-error></p>
</div>
<footer class="agreement-modal__footer">
<button class="agreement-button" type="button" data-delete-task-close>取消</button>
<button class="agreement-button agreement-button--danger" type="button" data-delete-task-confirm><span class="material-icons-outlined" aria-hidden="true">delete_outline</span><span data-delete-task-confirm-label>确认删除</span></button>
</footer>
</section>
</div>
<p class="sr-only" role="status" aria-live="polite" data-agreement-announcer></p>
<script>
(function () {
'use strict';
var root = document.querySelector('[data-agreement-signing]');
if (!root || root.dataset.ready === 'true') {
return;
}
root.dataset.ready = 'true';
var tabs = Array.prototype.slice.call(root.querySelectorAll('[data-agreement-tab]'));
var panels = Array.prototype.slice.call(root.querySelectorAll('[data-agreement-panel]'));
var form = root.querySelector('[data-agreement-form]');
var announcer = root.querySelector('[data-agreement-announcer]');
var subjectModal = root.querySelector('[data-subject-modal]');
var archiveModal = root.querySelector('[data-archive-modal]');
var archiveConfirmForm = root.querySelector('[data-archive-confirm-form]');
var archiveTargetForm = null;
var lastArchiveTrigger = null;
var deleteTaskModal = root.querySelector('[data-delete-task-modal]');
var deleteTaskTargetForm = null;
var lastDeleteTaskTrigger = null;
var deletingTask = false;
var taskLoadRequest = 0;
var subjectList = root.querySelector('[data-subject-list]');
var subjectDeletePanel = root.querySelector('[data-subject-delete-panel]');
var subjectDeleteTarget = null;
var subjectForm = root.querySelector('[data-subject-form]');
var subjectSelect = root.querySelector('[data-signing-subject-select]');
var subjectFormTitle = root.querySelector('[data-subject-form-title]');
var subjectFormError = root.querySelector('[data-subject-form-error]');
var subjectFormCancel = root.querySelector('[data-subject-form-cancel]');
var subjectFormSubmit = root.querySelector('[data-subject-form-submit]');
var subjectIdInput = root.querySelector('[data-subject-id]');
var subjectNameInput = root.querySelector('[data-subject-name]');
var subjectCodeInput = root.querySelector('[data-subject-code]');
var courierSelect = root.querySelector('[data-courier-select]');
var courierSearchWrap = root.querySelector('[data-courier-search-wrap]');
var courierSearch = root.querySelector('[data-courier-search]');
var courierOptionsList = root.querySelector('[data-courier-options]');
var courierControl = root.querySelector('[data-courier-control]');
var courierLabel = root.querySelector('label[for="agreement-courier"]');
var partnerTypeInputs = Array.prototype.slice.call(root.querySelectorAll('[data-partner-type]'));
var supplierControl = root.querySelector('[data-supplier-control]');
var supplierIdInput = root.querySelector('[data-signing-supplier-id]');
var supplierOptions = @json($agreementSupplierOptions);
var documentSelect = form.querySelector('[data-document-type]');
var supplierContractSelect = form.querySelector('[data-supplier-contract-template]');
var documentOptions = Array.prototype.slice.call(documentSelect.options);
var currentPartnerType = 'courier';
var sendButton = root.querySelector('[data-sign-request-send]');
var esignAvailable = @json($esignConfigured);
var courierOptions = courierSelect ? Array.prototype.filter.call(courierSelect.options, function (option) {
return option.value !== '' && !option.disabled;
}).map(function (option) {
return { value: option.value, account: option.dataset.esignAccount || '' };
}) : [];
var originalCourierOptions = courierOptions;
var selectedSupplierId = '';
var visibleCourierIndexes = [];
var activeCourierIndex = -1;
var esignAccountInput = root.querySelector('input[name="esign_account"]');
var accountSignerTypeField = root.querySelector('[data-account-signer-type-field]');
var accountSignerTypeInputs = Array.prototype.slice.call(root.querySelectorAll('[data-account-signer-type]'));
var accountOrganizationField = root.querySelector('[data-account-organization-field]');
var accountOrganizationInput = root.querySelector('[data-account-organization-name]');
var accountSignerLabel = root.querySelector('[data-account-signer-label]');
var accountSignerHelp = root.querySelector('[data-account-signer-help]');
var operatorNameInput = root.querySelector('[data-account-operator-name]');
var operatorRequiredMark = root.querySelector('[data-account-operator-required]');
var entityChangeDeregisteredInput = root.querySelector('[data-entity-change-deregistered]');
var secondaryOperatorField = root.querySelector('[data-secondary-operator-field]');
var secondaryOperatorInput = root.querySelector('input[name="secondary_operator_name"]');
var authorizationSecondarySignerTypeInputs = Array.prototype.slice.call(root.querySelectorAll('[data-authorization-secondary-signer-type]'));
var operatorHelp = root.querySelector('[data-account-operator-help]');
var sharedCourierList = root.querySelector('[data-shared-courier-list]');
var sharedCourierAdd = root.querySelector('[data-shared-courier-add]');
var quoteVersionField = root.querySelector('[data-quote-confirmation-field]');
var quoteVersionSelect = root.querySelector('[data-quote-version]');
var archiveFieldset = root.querySelector('[data-archive-fieldset]');
var subjects = @json($agreementSubjectPayload);
var fallbackSubjectName = @json(company()?->name ?: '当前公司');
var cooperationSecondaryEsignAccount = @json($agreementCooperationSecondaryEsignAccount);
var secondaryEsignAccountInput = root.querySelector('input[name="secondary_esign_account"]');
var lastSubjectTrigger = null;
var quotePreviewRequest = 0;
function announce(message) {
if (announcer) {
announcer.textContent = '';
window.setTimeout(function () {
announcer.textContent = message;
}, 20);
}
}
function closeArchiveModal() {
archiveModal.hidden = true;
archiveModal.setAttribute('aria-hidden', 'true');
archiveTargetForm = null;
if (lastArchiveTrigger && lastArchiveTrigger.isConnected) {
lastArchiveTrigger.focus();
}
}
function openArchiveModal(button) {
archiveTargetForm = button.closest('[data-archive-form]');
lastArchiveTrigger = button;
archiveConfirmForm.reset();
archiveConfirmForm.querySelector('[data-archive-error]').textContent = '';
archiveConfirmForm.querySelector('textarea').removeAttribute('aria-invalid');
archiveConfirmForm.querySelector('[data-archive-task-number]').textContent = archiveTargetForm.dataset.taskNumber;
archiveModal.hidden = false;
archiveModal.setAttribute('aria-hidden', 'false');
archiveConfirmForm.querySelector('input:checked').focus();
}
function closeDeleteTaskModal() {
if (deletingTask) {
return;
}
deleteTaskModal.hidden = true;
deleteTaskModal.setAttribute('aria-hidden', 'true');
deleteTaskTargetForm = null;
if (lastDeleteTaskTrigger && lastDeleteTaskTrigger.isConnected) {
lastDeleteTaskTrigger.focus();
}
}
function openDeleteTaskModal(button) {
deleteTaskTargetForm = button.closest('[data-delete-task-form]');
lastDeleteTaskTrigger = button;
deleteTaskModal.querySelector('[data-delete-task-number]').textContent = deleteTaskTargetForm.dataset.taskNumber;
deleteTaskModal.querySelector('[data-delete-task-description]').textContent = deleteTaskTargetForm.dataset.taskDescription;
deleteTaskModal.querySelector('[data-delete-task-error]').textContent = '';
deleteTaskModal.hidden = false;
deleteTaskModal.setAttribute('aria-hidden', 'false');
deleteTaskModal.querySelector('button[data-delete-task-close]').focus();
}
async function loadTasks(url, options) {
var requestId = ++taskLoadRequest;
var panel = root.querySelector('[data-agreement-panel="tasks"]');
var focused = panel.contains(document.activeElement) ? document.activeElement : null;
var focusedId = focused ? focused.id : '';
var focusedScope = focused ? focused.dataset.taskScope : '';
panel.setAttribute('aria-busy', 'true');
panel.querySelector('[data-task-load-error]').textContent = '';
try {
var response = await fetch(url.toString(), {
credentials: 'same-origin',
headers: { 'Accept': 'text/html', 'X-Requested-With': 'XMLHttpRequest' }
});
if (!response.ok) {
throw new Error('任务列表加载失败');
}
var doc = new DOMParser().parseFromString(await response.text(), 'text/html');
var nextPanel = doc.querySelector('[data-agreement-panel="tasks"]');
if (!nextPanel) {
throw new Error('任务列表不可用');
}
if (requestId !== taskLoadRequest) {
return;
}
panel.replaceChildren.apply(panel, Array.prototype.slice.call(nextPanel.childNodes));
var nextFocus = focusedId ? document.getElementById(focusedId) : (focusedScope ? panel.querySelector('[data-task-scope="' + focusedScope + '"]') : null);
if (nextFocus && document.activeElement === document.body) {
nextFocus.focus();
}
if (!options || options.updateUrl !== false) {
window.history.pushState({ agreementView: 'tasks' }, '', url.toString());
}
announce('签署任务列表已更新');
} catch (error) {
if (requestId === taskLoadRequest) {
panel.querySelector('[data-task-load-error]').textContent = '任务列表加载失败,已保留原列表。请重新查询。';
}
} finally {
if (requestId === taskLoadRequest) {
panel.removeAttribute('aria-busy');
}
}
}
root.addEventListener('click', function (event) {
if (event.target.closest('[data-start-agreement]')) {
showTab('create');
refreshPreview();
return;
}
var archiveOpen = event.target.closest('[data-archive-open]');
if (archiveOpen) {
openArchiveModal(archiveOpen);
return;
}
if (event.target.closest('[data-archive-modal-close]')) {
closeArchiveModal();
return;
}
var deleteTaskOpen = event.target.closest('[data-delete-task-open]');
if (deleteTaskOpen) {
openDeleteTaskModal(deleteTaskOpen);
return;
}
if (event.target.closest('[data-delete-task-close]')) {
closeDeleteTaskModal();
return;
}
var panel = event.target.closest('[data-agreement-panel="tasks"]');
if (!panel) {
return;
}
var link = event.target.closest('a[href]');
if (link && !event.ctrlKey && !event.metaKey && !event.shiftKey && event.button === 0) {
var url = new URL(link.href);
if (url.origin === window.location.origin && url.pathname === window.location.pathname) {
event.preventDefault();
url.searchParams.set('agreement_view', 'tasks');
loadTasks(url);
}
}
if (event.target.closest('[data-task-reset]')) {
var resetUrl = new URL(window.location.href);
['agreement_search', 'agreement_status', 'agreement_type', 'agreement_task_page', 'agreement_quote_page', 'agreement_page'].forEach(function (key) {
resetUrl.searchParams.delete(key);
});
resetUrl.searchParams.set('agreement_view', 'tasks');
loadTasks(resetUrl);
}
});
root.addEventListener('submit', function (event) {
if (!event.target.matches('[data-task-filter-form]')) {
return;
}
event.preventDefault();
var url = new URL(event.target.action);
new FormData(event.target).forEach(function (value, key) {
if (value !== '') {
url.searchParams.set(key, value);
}
});
loadTasks(url);
});
archiveConfirmForm.addEventListener('submit', function (event) {
event.preventDefault();
if (!archiveTargetForm) {
return;
}
var code = archiveConfirmForm.querySelector('input[name="archive_reason_code"]:checked').value;
var note = archiveConfirmForm.querySelector('textarea[name="archive_note"]');
if (code === 'other' && !note.value.trim()) {
archiveConfirmForm.querySelector('[data-archive-error]').textContent = '选择“其他”时请填写归档说明。';
note.setAttribute('aria-invalid', 'true');
note.focus();
return;
}
archiveTargetForm.querySelector('[data-archive-reason-code]').value = code;
archiveTargetForm.querySelector('[data-archive-note]').value = note.value.trim();
root.querySelector('[data-archive-confirm]').disabled = true;
archiveTargetForm.requestSubmit();
});
deleteTaskModal.querySelector('[data-delete-task-confirm]').addEventListener('click', async function () {
if (!deleteTaskTargetForm || deletingTask) {
return;
}
var targetForm = deleteTaskTargetForm;
var errorElement = deleteTaskModal.querySelector('[data-delete-task-error]');
var confirmLabel = deleteTaskModal.querySelector('[data-delete-task-confirm-label]');
deletingTask = true;
errorElement.textContent = '';
confirmLabel.textContent = '删除中…';
deleteTaskModal.querySelectorAll('button').forEach(function (button) { button.disabled = true; });
try {
var response = await fetch(targetForm.action, {
method: 'POST', credentials: 'same-origin', body: new FormData(targetForm),
headers: { 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest' }
});
var result = await response.json().catch(function () {
throw new Error('无法确认删除结果,请重新查询任务列表后再试。');
});
if (!response.ok) {
throw new Error(result.message || '删除失败,任务已保留,请稍后重试。');
}
var refreshUrl = new URL(window.location.href);
var quoteTask = targetForm.closest('tr').hasAttribute('data-quote-task-row');
var pageKey = quoteTask ? 'agreement_quote_page' : 'agreement_task_page';
var taskPage = Number(refreshUrl.searchParams.get(pageKey) || 1);
var previousPage = taskPage > 1 && targetForm.closest('tbody').querySelectorAll(quoteTask ? '[data-quote-task-row]' : '[data-agreement-task-row]').length === 1;
if (previousPage) {
refreshUrl.searchParams.set(pageKey, String(taskPage - 1));
}
deletingTask = false;
closeDeleteTaskModal();
// Remove the deleted row even if refreshing the list fails.
targetForm.closest('tr').remove();
await loadTasks(refreshUrl, { updateUrl: previousPage });
root.querySelector('[data-task-filter-form] button[type="submit"]').focus();
announce(result.message);
} catch (error) {
errorElement.textContent = error.name === 'TypeError' ? '网络连接失败,无法确认删除结果,请重新查询任务列表。' : (error.message || '删除失败,任务已保留,请稍后重试。');
} finally {
deletingTask = false;
confirmLabel.textContent = '确认删除';
deleteTaskModal.querySelectorAll('button').forEach(function (button) { button.disabled = false; });
}
});
function subjectUrl(template, id) {
return template.replace('__subject__', encodeURIComponent(String(id)));
}
function resetSubjectForm() {
if (!subjectForm) {
return;
}
subjectForm.reset();
subjectIdInput.value = '';
subjectFormTitle.textContent = '新增公司主体';
subjectFormCancel.hidden = true;
subjectFormError.textContent = '';
subjectFormSubmit.disabled = false;
subjectFormSubmit.querySelector('span:last-child').textContent = '保存主体';
}
function renderSubjectSelect(preferredId) {
if (!subjectSelect) {
return;
}
var currentOption = subjectSelect.options[subjectSelect.selectedIndex];
var currentId = currentOption && currentOption.dataset.subjectId;
var selected = subjects.find(function (subject) {
return String(subject.id) === String(preferredId || currentId);
}) || subjects.find(function (subject) {
return subject.is_default;
}) || subjects[0];
subjectSelect.innerHTML = '';
if (!subjects.length) {
var fallbackOption = document.createElement('option');
fallbackOption.value = fallbackSubjectName;
fallbackOption.dataset.subjectFallback = 'true';
fallbackOption.textContent = fallbackSubjectName + '(当前公司)';
subjectSelect.appendChild(fallbackOption);
return;
}
subjects.forEach(function (subject) {
var option = document.createElement('option');
option.value = subject.name;
option.dataset.subjectId = String(subject.id);
option.textContent = subject.name + (subject.is_default ? '(默认)' : '');
option.selected = selected && String(selected.id) === String(subject.id);
subjectSelect.appendChild(option);
});
}
function syncSubjectLinkedNames(subjectName) {
if (!subjectName) {
return;
}
root.querySelectorAll('[data-subject-linked-name]').forEach(function (control) {
control.value = subjectName;
});
}
function renderSubjectList() {
if (!subjectList) {
return;
}
subjectList.innerHTML = '';
if (!subjects.length) {
var empty = document.createElement('div');
empty.className = 'agreement-subject-empty';
empty.textContent = '还没有主体档案,请先在下方新增一个公司主体。';
subjectList.appendChild(empty);
return;
}
subjects.forEach(function (subject) {
var item = document.createElement('div');
item.className = 'agreement-subject-item' + (subject.is_default ? ' agreement-subject-item--default' : '');
var info = document.createElement('div');
var name = document.createElement('div');
name.className = 'agreement-subject-item__name';
var nameText = document.createElement('span');
nameText.className = 'agreement-subject-item__name-text';
nameText.textContent = subject.name;
name.appendChild(nameText);
if (subject.is_default) {
var badge = document.createElement('span');
badge.className = 'agreement-status agreement-status--success';
badge.textContent = '默认';
name.appendChild(badge);
}
info.appendChild(name);
if (subject.unified_social_credit_code) {
var code = document.createElement('div');
code.className = 'agreement-subject-item__code';
code.textContent = '统一社会信用代码:' + subject.unified_social_credit_code;
info.appendChild(code);
}
var actions = document.createElement('div');
actions.className = 'agreement-subject-item__actions';
var edit = document.createElement('button');
edit.className = 'agreement-button';
edit.type = 'button';
edit.dataset.subjectEdit = String(subject.id);
edit.textContent = '编辑';
actions.appendChild(edit);
if (!subject.is_default) {
var makeDefault = document.createElement('button');
makeDefault.className = 'agreement-button';
makeDefault.type = 'button';
makeDefault.dataset.subjectDefault = String(subject.id);
makeDefault.textContent = '设为默认';
actions.appendChild(makeDefault);
}
var remove = document.createElement('button');
remove.className = 'agreement-button agreement-button--danger';
remove.type = 'button';
remove.dataset.subjectDelete = String(subject.id);
remove.setAttribute('aria-label', '删除公司主体“' + subject.name + '”');
remove.textContent = '删除';
actions.appendChild(remove);
item.appendChild(info);
item.appendChild(actions);
subjectList.appendChild(item);
});
}
function openSubjectModal(subjectId) {
if (!subjectModal) {
return;
}
lastSubjectTrigger = document.activeElement;
subjectModal.hidden = false;
subjectModal.setAttribute('aria-hidden', 'false');
renderSubjectList();
if (subjectId) {
var subject = subjects.find(function (item) {
return String(item.id) === String(subjectId);
});
if (subject) {
subjectIdInput.value = subject.id;
subjectNameInput.value = subject.name;
subjectCodeInput.value = subject.unified_social_credit_code || '';
subjectFormTitle.textContent = '编辑公司主体';
subjectFormCancel.hidden = false;
}
} else {
resetSubjectForm();
}
window.setTimeout(function () {
subjectNameInput && subjectNameInput.focus();
}, 0);
}
function closeSubjectModal() {
if (!subjectModal) {
return;
}
subjectModal.hidden = true;
subjectModal.setAttribute('aria-hidden', 'true');
closeSubjectDelete();
resetSubjectForm();
if (lastSubjectTrigger && typeof lastSubjectTrigger.focus === 'function') {
lastSubjectTrigger.focus();
}
}
function closeSubjectDelete() {
subjectDeletePanel.hidden = true;
subjectDeleteTarget = null;
}
async function requestSubject(url, body) {
var response = await fetch(url, {
method: 'POST',
headers: {
Accept: 'application/json',
'X-Requested-With': 'XMLHttpRequest',
},
body: body,
});
var payload = await response.json().catch(function () { return {}; });
if (!response.ok) {
var validationMessage = payload.errors ? Object.values(payload.errors).flat()[0] : null;
var error = new Error(validationMessage || payload.message || '主体操作失败,请稍后重试。');
error.payload = payload;
throw error;
}
return payload;
}
function updateUrl(view, replace) {
var url = new URL(window.location.href);
url.searchParams.set('agreement_view', view);
url.searchParams.delete('agreement_step');
window.history[replace ? 'replaceState' : 'pushState']({ agreementView: view }, '', url.toString());
}
function showTab(name, options) {
var settings = options || {};
var selected = tabs.some(function (tab) {
return tab.dataset.agreementTab === name;
}) ? name : 'tasks';
tabs.forEach(function (tab) {
var active = tab.dataset.agreementTab === selected;
tab.setAttribute('aria-selected', active ? 'true' : 'false');
tab.tabIndex = active ? 0 : -1;
});
panels.forEach(function (panel) {
panel.hidden = panel.dataset.agreementPanel !== selected;
});
if (settings.updateUrl !== false) {
updateUrl(selected, Boolean(settings.replace));
}
if (settings.focus) {
var activeTab = tabs.find(function (tab) {
return tab.dataset.agreementTab === selected;
});
activeTab && activeTab.focus();
}
announce(selected === 'tasks' ? '已切换到签署任务' : selected === 'create' ? '已切换到发起签章' : '已切换到模板管理');
}
function selectedDocument() {
var select = form.querySelector('[data-document-type]');
return select.options[select.selectedIndex];
}
function syncPartnerType() {
var selected = partnerTypeInputs.find(function (input) { return input.checked; });
var type = selected ? selected.value : 'courier';
var supplier = type === 'supplier';
if (type !== currentPartnerType) {
closeCourierOptions();
courierSelect.value = '';
courierSearch.value = '';
esignAccountInput.value = '';
delete esignAccountInput.dataset.autoFilled;
accountOrganizationInput.value = '';
operatorNameInput.value = '';
secondaryEsignAccountInput.value = '';
secondaryOperatorInput.value = '';
root.querySelector('[data-request-error]').textContent = '';
supplierIdInput.value = '';
['former_company_name', 'cooperation_party_b_name', 'principal_name'].forEach(function (name) {
var input = form.querySelector('[name="' + name + '"]');
if (input) input.value = '';
});
}
currentPartnerType = type;
courierOptions = supplier ? supplierOptions : originalCourierOptions;
courierSelect.replaceChildren(new Option('请选择', ''));
courierOptions.forEach(function (item) {
var option = new Option(item.value, item.value);
option.dataset.esignAccount = item.account;
courierSelect.appendChild(option);
});
supplierIdInput.disabled = !supplier;
courierSearch.placeholder = supplier ? '输入供应商简称、全称或编码搜索' : '输入快递名称搜索';
courierOptionsList.setAttribute('aria-label', supplier ? '供应商资料' : '快递资料');
supplierControl.hidden = !supplier;
supplierControl.textContent = supplierOptions.length ? '按供应商简称、企业全称或编码搜索,选择后自动带入易签宝账号。' : '供应商资料暂不可用,请稍后重试。';
courierLabel.htmlFor = courierSearch.id;
root.querySelector('[data-partner-name-label]').textContent = supplier ? '供应商名称' : '快递公司';
root.querySelector('[data-partner-account-help]').textContent = supplier
? '选择供应商后自动带出工作平台的电子合同经办人账号;发送前请核对企业全称、账号及实名认证姓名,资料未维护时可手工填写。'
: '选择快递公司后自动带出工作平台的“电子签章经办人”(dzqzjbr);如资料未维护,可手工填写对方在 E 签宝实名绑定的手机号或邮箱。';
// Rebuild the small template list so unavailable options are absent on every browser.
var previousDocument = documentSelect.value;
documentSelect.replaceChildren();
documentOptions.forEach(function (option) {
var types = (option.dataset.partnerTypes || 'courier').split(' ');
if (types.indexOf(type) !== -1) documentSelect.appendChild(option);
});
if (Array.prototype.some.call(documentSelect.options, function (option) { return option.value === previousDocument; })) {
documentSelect.value = previousDocument;
} else {
documentSelect.value = 'account-proof';
}
syncCourierSelection();
}
function fieldValue(selector, fallback) {
var field = form.querySelector(selector);
return field && field.value.trim() ? field.value.trim() : fallback;
}
function sharedCourierValues() {
if (!sharedCourierList) {
return [];
}
return Array.prototype.slice.call(sharedCourierList.querySelectorAll('[data-shared-courier]'))
.map(function (control) { return control.value.trim(); })
.filter(Boolean);
}
function updateSharedCourierRemoveButtons() {
if (!sharedCourierList) {
return;
}
var rows = sharedCourierList.querySelectorAll('.agreement-shared-courier-row');
rows.forEach(function (row) {
var remove = row.querySelector('[data-shared-courier-remove]');
if (remove) {
remove.disabled = rows.length <= 1;
}
});
}
function addSharedCourier() {
if (!sharedCourierList) {
return;
}
var firstRow = sharedCourierList.querySelector('.agreement-shared-courier-row');
if (!firstRow) {
return;
}
var row = firstRow.cloneNode(true);
var input = row.querySelector('[data-shared-courier]');
var remove = row.querySelector('[data-shared-courier-remove]');
var count = sharedCourierList.querySelectorAll('.agreement-shared-courier-row').length + 1;
if (input) {
input.value = '';
input.placeholder = '第' + count + '家快递公司名称';
input.disabled = false;
}
if (remove) {
remove.disabled = false;
}
sharedCourierList.appendChild(row);
updateSharedCourierRemoveButtons();
input && input.focus();
refreshPreview();
}
function syncEsignAccount() {
if (!courierSelect || !esignAccountInput) {
return;
}
var option = courierSelect.options[courierSelect.selectedIndex];
var account = option && option.dataset.esignAccount ? option.dataset.esignAccount.trim() : '';
if (currentPartnerType === 'supplier') {
var supplier = courierOptions.find(function (item) { return String(item.id) === supplierIdInput.value; });
if (selectedSupplierId !== supplierIdInput.value) {
selectedSupplierId = supplierIdInput.value;
esignAccountInput.value = '';
delete esignAccountInput.dataset.autoFilled;
accountOrganizationInput.value = supplier ? supplier.company : '';
operatorNameInput.value = supplier ? supplier.operator : '';
['former_company_name', 'cooperation_party_b_name', 'principal_name'].forEach(function (name) {
var input = form.querySelector('[name="' + name + '"]');
if (input) input.value = supplier ? supplier.company : '';
});
}
supplierControl.textContent = supplier
? supplier.value + ' · ' + supplier.code + (supplier.company ? ' · ' + supplier.company : '') + (supplier.account ? '' : ';未维护易签宝账号,请手工填写并核对。')
: (supplierOptions.length ? '请从搜索结果选择供应商。' : '供应商资料暂不可用,请稍后重试。');
} else {
selectedSupplierId = '';
}
if (account !== '') {
esignAccountInput.value = account;
esignAccountInput.dataset.autoFilled = 'true';
announce(currentPartnerType === 'supplier' ? '已带出该供应商的易签宝账号' : '已带出该快递的电子签章经办人账号');
} else if (esignAccountInput.dataset.autoFilled === 'true') {
esignAccountInput.value = '';
delete esignAccountInput.dataset.autoFilled;
}
}
function closeCourierOptions() {
if (!courierSearch || !courierOptionsList) {
return;
}
courierOptionsList.hidden = true;
courierSearch.setAttribute('aria-expanded', 'false');
courierSearch.removeAttribute('aria-activedescendant');
activeCourierIndex = -1;
}
function renderCourierOptions(query) {
if (!courierSearch || !courierOptionsList) {
return;
}
var normalizedQuery = String(query || '').trim().toLocaleLowerCase();
var matches = [];
courierOptions.forEach(function (option, index) {
var searchText = [option.value, option.company || '', option.code || ''].join(' ').toLocaleLowerCase();
if (normalizedQuery === '' || searchText.indexOf(normalizedQuery) !== -1) {
matches.push(index);
}
});
visibleCourierIndexes = matches.slice(0, 80);
courierOptionsList.innerHTML = '';
if (visibleCourierIndexes.length === 0) {
var empty = document.createElement('div');
empty.className = 'agreement-courier-options-status';
empty.setAttribute('role', 'status');
empty.textContent = currentPartnerType === 'supplier'
? (normalizedQuery === '' ? '暂无可选供应商资料' : '没有匹配的供应商')
: (normalizedQuery === '' ? '暂无可选快递资料' : '没有匹配的快递名称');
courierOptionsList.appendChild(empty);
} else {
visibleCourierIndexes.forEach(function (optionIndex) {
var option = courierOptions[optionIndex];
var item = document.createElement('div');
item.className = 'agreement-courier-option';
item.id = 'agreement-courier-option-' + optionIndex;
item.setAttribute('role', 'option');
item.setAttribute('aria-selected', courierSelect.value === option.value ? 'true' : 'false');
item.dataset.courierOption = String(optionIndex);
item.textContent = currentPartnerType === 'supplier' ? option.value + ' · ' + option.code + (option.company ? ' · ' + option.company : '') : option.value;
courierOptionsList.appendChild(item);
});
if (matches.length > visibleCourierIndexes.length) {
var status = document.createElement('div');
status.className = 'agreement-courier-options-status';
status.setAttribute('role', 'status');
status.textContent = '匹配到 ' + matches.length + ' 项,当前显示前 80 项;继续输入可缩小范围';
courierOptionsList.appendChild(status);
}
}
courierOptionsList.hidden = false;
courierSearch.setAttribute('aria-expanded', 'true');
activeCourierIndex = -1;
courierSearch.removeAttribute('aria-activedescendant');
}
function setActiveCourierOption(position) {
if (!courierOptionsList || visibleCourierIndexes.length === 0) {
return;
}
activeCourierIndex = (position + visibleCourierIndexes.length) % visibleCourierIndexes.length;
var optionIndex = visibleCourierIndexes[activeCourierIndex];
var optionElement = courierOptionsList.querySelector('[data-courier-option="' + optionIndex + '"]');
courierOptionsList.querySelectorAll('.agreement-courier-option').forEach(function (item) {
item.classList.toggle('is-active', item === optionElement);
});
courierSearch.setAttribute('aria-activedescendant', 'agreement-courier-option-' + optionIndex);
optionElement && optionElement.scrollIntoView({ block: 'nearest' });
}
function syncCourierSelection() {
if (!courierSelect || !courierSearch) {
return;
}
var enteredName = courierSearch.value.trim();
var option = courierOptions.find(function (item) {
return item.value.toLocaleLowerCase() === enteredName.toLocaleLowerCase();
});
supplierIdInput.value = currentPartnerType === 'supplier' && option ? option.id : '';
if (option) {
courierSearch.value = option.value;
courierSelect.value = option.value;
courierSearch.setCustomValidity('');
} else {
courierSelect.value = '';
courierSearch.setCustomValidity(currentPartnerType === 'supplier' ? '请从供应商资料中选择供应商' : (enteredName === '' ? '请选择快递公司' : '请从快递资料中选择快递公司'));
}
}
function chooseCourierOption(index) {
if (!courierSearch || !courierSelect || !courierOptions[index]) {
return;
}
courierSearch.value = courierOptions[index].value;
syncCourierSelection();
closeCourierOptions();
syncEsignAccount();
refreshPreview();
}
function initializeCourierSearch() {
if (!courierSelect || !courierSearchWrap || !courierSearch || !courierOptionsList) {
return;
}
courierSearchWrap.hidden = false;
courierSelect.classList.add('agreement-courier-native-select--enhanced');
courierSelect.setAttribute('aria-hidden', 'true');
courierSelect.tabIndex = -1;
courierSelect.required = false;
courierSearch.value = courierSelect.value;
courierSearch.required = true;
if (courierLabel) {
courierLabel.htmlFor = courierSearch.id;
}
syncCourierSelection();
courierSearch.addEventListener('focus', function () {
courierSearch.select();
renderCourierOptions('');
});
courierSearch.addEventListener('input', function () {
syncCourierSelection();
renderCourierOptions(courierSearch.value);
syncEsignAccount();
refreshPreview();
});
courierSearch.addEventListener('keydown', function (event) {
if (event.key === 'ArrowDown') {
event.preventDefault();
if (courierOptionsList.hidden) {
renderCourierOptions(courierSearch.value);
}
setActiveCourierOption(activeCourierIndex + 1);
} else if (event.key === 'ArrowUp') {
event.preventDefault();
if (courierOptionsList.hidden) {
renderCourierOptions(courierSearch.value);
}
setActiveCourierOption(activeCourierIndex < 0 ? visibleCourierIndexes.length - 1 : activeCourierIndex - 1);
} else if (event.key === 'Enter' && !courierOptionsList.hidden) {
event.preventDefault();
var selectedIndex = activeCourierIndex >= 0
? visibleCourierIndexes[activeCourierIndex]
: visibleCourierIndexes.find(function (optionIndex) {
return courierOptions[optionIndex].value.toLocaleLowerCase() === courierSearch.value.trim().toLocaleLowerCase();
});
if (selectedIndex === undefined && visibleCourierIndexes.length === 1) {
selectedIndex = visibleCourierIndexes[0];
}
if (selectedIndex !== undefined) {
chooseCourierOption(selectedIndex);
}
} else if (event.key === 'Escape') {
closeCourierOptions();
}
});
courierSearch.addEventListener('blur', function () {
window.setTimeout(function () {
if (courierControl && !courierControl.contains(document.activeElement)) {
closeCourierOptions();
}
}, 0);
});
courierOptionsList.addEventListener('mousedown', function (event) {
if (event.target.closest('[data-courier-option]')) {
event.preventDefault();
}
});
courierOptionsList.addEventListener('click', function (event) {
var optionElement = event.target.closest('[data-courier-option]');
if (optionElement) {
chooseCourierOption(Number(optionElement.dataset.courierOption));
}
});
root.addEventListener('click', function (event) {
if (courierControl && !courierControl.contains(event.target)) {
closeCourierOptions();
}
});
}
function setText(selector, value) {
root.querySelectorAll(selector).forEach(function (target) {
target.textContent = value;
});
}
function refreshSignerAccountLabels(templateType) {
var labels = {
primary: '对方 E 签宝账号',
secondary: '第二签署方 E 签宝账号'
};
if (templateType === 'cooperation-contract') {
labels.primary = '快递方 E 签宝账号';
if (currentPartnerType === 'supplier') {
labels.primary = '供应商 E 签宝账号';
}
labels.secondary = '我方 E 签宝账号';
} else if (templateType === 'entity-change') {
labels.primary = entityChangeDeregisteredInput && entityChangeDeregisteredInput.checked
? '原公司法人个人 E 签宝账号'
: '变更前主体 E 签宝账号';
labels.secondary = '变更后主体 E 签宝账号';
} else if (templateType === 'authorization') {
labels.primary = '委托方 E 签宝账号';
labels.secondary = '受托方 E 签宝账号';
}
setText('[data-primary-esign-label]', labels.primary);
setText('[data-secondary-esign-label]', labels.secondary);
}
function formatDateField(selector, fallback) {
var value = fieldValue(selector, '');
var parts = value.split('-');
if (parts.length !== 3) {
return fallback;
}
return Number(parts[0]) + ' 年 ' + Number(parts[1]) + ' 月 ' + Number(parts[2]) + ' 日';
}
function activateTemplate(templateType) {
root.querySelectorAll('[data-template-fields]').forEach(function (group) {
var active = group.dataset.templateFields === templateType || (templateType === 'supplier-cooperation' && group.dataset.templateFields === 'cooperation-contract');
group.hidden = !active;
group.querySelectorAll('input, select, textarea').forEach(function (control) {
control.disabled = !active;
});
});
root.querySelectorAll('[data-template-preview]').forEach(function (preview) {
preview.hidden = preview.dataset.templatePreview !== templateType;
});
if (quoteVersionField && quoteVersionSelect) {
var quoteActive = templateType === 'quote-confirmation';
quoteVersionField.hidden = !quoteActive;
quoteVersionSelect.disabled = !quoteActive;
quoteVersionSelect.required = quoteActive;
if (!quoteActive) {
quoteVersionSelect.value = '';
}
if (archiveFieldset) {
var automaticArchive = archiveFieldset.querySelector('input[value="auto"]');
var manualArchive = archiveFieldset.querySelector('input[value="manual"]');
archiveFieldset.querySelector('legend').textContent = quoteActive ? '回传归档(报价确认单固定自动归档)' : '回传归档';
if (quoteActive && automaticArchive) {
automaticArchive.checked = true;
}
if (manualArchive) {
manualArchive.disabled = quoteActive;
}
}
}
}
function setPreviewValue(key, value) {
var preview = root.querySelector('[data-template-preview]:not([hidden])');
if (!preview) {
return;
}
preview.querySelectorAll('[data-preview-bind="' + key + '"]').forEach(function (target) {
target.textContent = value;
});
}
function quoteVersionOption() {
if (!quoteVersionSelect || !quoteVersionSelect.value) {
return null;
}
return quoteVersionSelect.options[quoteVersionSelect.selectedIndex];
}
function renderQuoteMatrix(values, message) {
var target = root.querySelector('[data-template-preview="quote-confirmation"] [data-preview-bind="quoteMatrix"]');
if (!target) {
return;
}
target.textContent = '';
if (!Array.isArray(values) || values.length === 0) {
target.textContent = message || '该报价版本没有可展示的报价明细';
return;
}
var table = document.createElement('table');
var body = document.createElement('tbody');
values.forEach(function (row, rowIndex) {
var rowElement = document.createElement('tr');
(Array.isArray(row) ? row : [row]).forEach(function (cell) {
var cellElement = document.createElement(rowIndex === 0 ? 'th' : 'td');
cellElement.textContent = cell === null || cell === undefined ? '' : String(cell);
rowElement.appendChild(cellElement);
});
body.appendChild(rowElement);
});
table.appendChild(body);
target.appendChild(table);
}
async function loadQuotePreview() {
var option = quoteVersionOption();
var requestId = ++quotePreviewRequest;
if (!option || !option.dataset.previewUrl) {
renderQuoteMatrix([], '请选择报价版本后查看报价明细');
return;
}
renderQuoteMatrix([], '正在加载完整报价明细…');
try {
var response = await fetch(option.dataset.previewUrl, {
headers: { 'Accept': 'application/json' },
credentials: 'same-origin'
});
var payload = await response.json();
if (!response.ok) {
throw new Error(payload.message || '报价明细加载失败');
}
if (requestId !== quotePreviewRequest) {
return;
}
setPreviewValue('quoteVersion', payload.version_code || '待选择');
setPreviewValue('quoteCarrier', payload.carrier_name || '待选择');
setPreviewValue('quoteType', payload.quote_type || '待选择');
setPreviewValue('quotePartyA', payload.party_a || '待填写');
setPreviewValue('quotePartyB', payload.party_b || payload.carrier_name || '待选择');
setPreviewValue('quoteEffectiveDate', payload.effective_date || '待选择');
setPreviewValue('quoteExpiryDate', payload.expiry_date || '长期');
setPreviewValue('quoteFaceFee', payload.face_fee || '按报价明细');
setPreviewValue('quoteBubbleCoefficient', payload.bubble_coefficient || '按报价明细');
renderQuoteMatrix(payload.values, '该报价版本没有可展示的报价明细');
} catch (error) {
if (requestId === quotePreviewRequest) {
renderQuoteMatrix([], error.message || '报价明细加载失败,请重试');
}
}
}
function authorizationItemNumbers(templateType) {
var items = Array.prototype.slice.call(form.querySelectorAll('[data-authorization-item]'));
var selected = items.filter(function (item) {
return item.checked;
}).map(function (item) {
return item.value;
});
var firstItem = items[0];
if (firstItem) {
firstItem.setCustomValidity(templateType === 'authorization' && selected.length === 0 ? '请至少选择一项授权事项' : '');
}
return selected.length ? selected.join('、') : '待选择';
}
function refreshPreview() {
var documentOption = selectedDocument();
var templateType = documentOption.value;
var supplierContract = currentPartnerType === 'supplier' && templateType === 'cooperation-contract';
var supplierUnavailable = currentPartnerType === 'supplier' && !supplierOptions.length;
sendButton.disabled = supplierUnavailable || !esignAvailable;
sendButton.title = supplierUnavailable ? '供应商资料暂不可用' : (esignAvailable ? '推送至E签宝' : 'E签宝尚未配置');
sendButton.querySelector('span:last-child').textContent = '推送至E签宝';
var courier = fieldValue('[name="courier_name"]', currentPartnerType === 'supplier' ? '供应商' : '快递公司');
var companyName = fieldValue('[name="company_full_name"]', '待填写公司全称');
var accountAgreement = templateType === 'account-proof' || templateType === 'account-change';
var entityChange = templateType === 'entity-change';
var cooperationContract = templateType === 'cooperation-contract';
var authorization = templateType === 'authorization';
var sharedContract = templateType === 'shared-contract';
var formerCompanyDeregistered = entityChange && entityChangeDeregisteredInput && entityChangeDeregisteredInput.checked;
var signerTypeFieldVisible = accountAgreement || cooperationContract || authorization || sharedContract;
var accountSignerTypeInput = accountSignerTypeInputs.find(function (input) {
return input.checked;
});
var accountSignerType = accountSignerTypeInput ? accountSignerTypeInput.value : 'organization';
var accountSignerIsPerson = accountAgreement && accountSignerType === 'person';
var otherSignerIsPerson = (cooperationContract || authorization) && accountSignerType === 'person';
var sharedSignerIsPerson = sharedContract && accountSignerType === 'person';
var trusteeSignerTypeInput = authorizationSecondarySignerTypeInputs.find(function (input) {
return input.checked;
});
var trusteeIsPerson = authorization && trusteeSignerTypeInput && trusteeSignerTypeInput.value === 'person';
accountSignerTypeInputs.forEach(function (input) {
input.disabled = !signerTypeFieldVisible;
});
if (accountSignerTypeField) {
accountSignerTypeField.hidden = !signerTypeFieldVisible;
setText('[data-signer-type-organization-title]', '企业签署');
setText('[data-signer-type-organization-help]', '企业名称和经办人姓名分别填写');
setText('[data-signer-type-person-title]', '个人签署');
setText('[data-signer-type-person-help]', '签署人姓名须与 E 签宝账号实名认证一致');
}
if (accountOrganizationField) {
accountOrganizationField.hidden = !accountAgreement;
}
if (accountOrganizationInput) {
accountOrganizationInput.disabled = !accountAgreement;
accountOrganizationInput.required = accountAgreement;
accountOrganizationInput.autocomplete = accountSignerIsPerson ? 'name' : 'organization';
accountOrganizationInput.placeholder = accountSignerIsPerson
? '填写对方在 E 签宝实名认证的姓名'
: '填写对方在 E 签宝认证的企业全称';
}
if (operatorNameInput) {
var needsPrimaryOperator = (sharedContract && !sharedSignerIsPerson) || (accountAgreement && !accountSignerIsPerson) || entityChange || ((cooperationContract || authorization) && !otherSignerIsPerson);
operatorNameInput.disabled = !needsPrimaryOperator;
operatorNameInput.required = needsPrimaryOperator;
operatorNameInput.placeholder = formerCompanyDeregistered
? '填写原公司法人 E 签宝实名认证姓名'
: '填写与 E 签宝账号匹配的实名姓名';
if (accountSignerIsPerson) {
operatorNameInput.value = accountOrganizationInput ? accountOrganizationInput.value : '';
}
root.querySelector('[data-primary-operator-field]').hidden = !needsPrimaryOperator;
setText('[data-primary-operator-label]', formerCompanyDeregistered ? '原公司法人 E 签宝实名认证姓名' : entityChange ? '变更前主体 E 签宝实名认证姓名' : '对方 E 签宝实名认证姓名');
}
if (operatorRequiredMark) {
operatorRequiredMark.hidden = !operatorNameInput.required;
}
if (operatorHelp) {
operatorHelp.textContent = sharedContract
? '填写物流商归属企业经办人的真实姓名,须与上方 E 签宝账号实名认证一致;快递名称填写在下方物流商名单。'
: '仅用于 E 签宝身份核验,不是收款人姓名;收款人姓名请填写在下方账户资料中。';
}
if (accountSignerLabel) {
accountSignerLabel.textContent = accountSignerIsPerson ? '对方签署个人姓名' : '对方签署企业全称';
}
if (accountSignerHelp) {
accountSignerHelp.textContent = accountSignerIsPerson
? '填写与 E 签宝账号实名一致的个人姓名;该姓名会作为个人签署人发送,不需要填写企业全称。'
: '必须与对方 E 签宝企业认证名称一致;这是签署主体,不要求与银行卡持卡人姓名一致。';
}
activateTemplate(supplierContract ? 'supplier-cooperation' : templateType);
root.querySelectorAll('[data-courier-contract-metadata]').forEach(function (field) {
var visible = cooperationContract && !supplierContract && (!field.hasAttribute('data-courier-contract-legal') || !otherSignerIsPerson);
field.hidden = !visible;
field.querySelectorAll('input').forEach(function (input) { input.disabled = !visible; });
});
root.querySelector('[data-supplier-contract-fields]').hidden = !supplierContract;
supplierContractSelect.disabled = !supplierContract;
root.querySelectorAll('[data-supplier-field-templates]').forEach(function (group) {
var active = supplierContract && group.dataset.supplierFieldTemplates.split(' ').indexOf(supplierContractSelect.value) !== -1;
group.hidden = !active;
group.querySelectorAll('input').forEach(function (input) { input.disabled = !active; });
});
root.querySelectorAll('[data-supplier-contract-preview]').forEach(function (preview) {
preview.hidden = preview.dataset.supplierContractPreview !== supplierContractSelect.value;
});
setText('[data-cooperation-party-b-label]', otherSignerIsPerson ? '乙方个人姓名(E 签宝实名)' : '乙方名称');
root.querySelector('[name="cooperation_party_b_name"]').placeholder = otherSignerIsPerson
? '填写合作人的 E 签宝实名认证姓名'
: (currentPartnerType === 'supplier' ? '供应商完整签署名称' : '快递公司完整签署名称');
setText('[data-principal-name-label]', otherSignerIsPerson ? '委托方个人姓名(E 签宝实名)' : '委托方企业全称');
setText('[data-trustee-name-label]', trusteeIsPerson ? '受托方个人姓名(E 签宝实名)' : '受托方企业全称');
refreshSignerAccountLabels(templateType);
var secondary = root.querySelector('[data-secondary-signer-fields]');
if (secondary) {
var needsSecondary = entityChange || cooperationContract || authorization;
secondary.hidden = !needsSecondary;
secondary.querySelectorAll('input').forEach(function (control) {
control.disabled = !needsSecondary;
control.required = needsSecondary;
if (templateType === 'cooperation-contract' && currentPartnerType === 'courier') {
control.value = cooperationSecondaryEsignAccount;
control.readOnly = true;
} else {
control.readOnly = false;
if (control.dataset.cooperationDefault === 'true') {
control.value = '';
delete control.dataset.cooperationDefault;
}
}
});
if (templateType === 'cooperation-contract' && currentPartnerType === 'courier' && secondaryEsignAccountInput) {
secondaryEsignAccountInput.dataset.cooperationDefault = 'true';
}
}
if (secondaryOperatorField) {
var needsSecondaryOperator = entityChange || cooperationContract || (authorization && !trusteeIsPerson);
secondaryOperatorField.hidden = !needsSecondaryOperator;
secondaryOperatorInput.disabled = !needsSecondaryOperator;
secondaryOperatorInput.required = needsSecondaryOperator;
setText('[data-secondary-operator-label]', entityChange ? '变更后主体 E 签宝实名认证姓名' : cooperationContract ? '我方 E 签宝实名认证姓名' : '受托方 E 签宝实名认证姓名');
}
var contractOption = supplierContractSelect.options[supplierContractSelect.selectedIndex];
var selectedMetadata = supplierContract ? contractOption.dataset : documentOption.dataset;
setText('[data-template-name]', selectedMetadata.name);
setText('[data-template-code]', selectedMetadata.code);
setText('[data-template-description]', supplierContract ? '原文件:' + selectedMetadata.file + ';正文和附件由双方签署并回传。' : formerCompanyDeregistered ? '原法人以个人身份签字,变更后公司仍须法人签字并盖章;双方分别接收签署请求。' : otherSignerIsPerson ? '使用合作人的个人实名认证姓名和账号签署。' : documentOption.dataset.description);
setText('[data-variable-template-name]', selectedMetadata.name);
setText('[data-variable-template-status]', '— 填写变量');
setText('[data-preview-template-code]', selectedMetadata.code);
setText('[data-preview-status-hint]', '已填写变量随表单更新');
setPreviewValue('company', companyName);
setPreviewValue('courier', courier);
setPreviewValue('signatureDate', formatDateField('[name="signature_date"]', '待填写'));
if (templateType === 'account-proof') {
setPreviewValue('proofEffectiveDate', formatDateField('[name="account_proof_effective_date"]', '待填写'));
setPreviewValue('proofAccountName', fieldValue('[name="account_proof_account_name"]', '待填写'));
setPreviewValue('proofBankName', fieldValue('[name="account_proof_bank_name"]', '待填写'));
setPreviewValue('proofBankAccount', fieldValue('[name="account_proof_bank_account"]', '待填写'));
setPreviewValue('proofSigner', '公司盖章');
}
if (templateType === 'account-change') {
setPreviewValue('accountChangeDate', formatDateField('[name="account_change_date"]', '待填写'));
setPreviewValue('oldAccountName', fieldValue('[name="old_account_name"]', '待填写'));
setPreviewValue('oldAccountNumber', fieldValue('[name="old_account_number"]', '待填写'));
setPreviewValue('oldAccountStopDate', formatDateField('[name="old_account_stop_date"]', '待填写'));
setPreviewValue('newAccountEffectiveDate', formatDateField('[name="new_account_effective_date"]', '待填写'));
setPreviewValue('newAccountName', fieldValue('[name="new_account_name"]', '待填写'));
setPreviewValue('newBankName', fieldValue('[name="new_bank_name"]', '待填写'));
setPreviewValue('newBankAccount', fieldValue('[name="new_bank_account"]', '待填写'));
setPreviewValue('changeSigner', '公司盖章');
}
if (templateType === 'entity-change') {
setPreviewValue('formerCompanyName', fieldValue('[name="former_company_name"]', '待填写'));
setPreviewValue('entityChangeDate', formatDateField('[name="entity_change_date"]', '待填写'));
setPreviewValue('changedCompanyName', fieldValue('[name="changed_company_name"]', '待填写'));
setPreviewValue('changedCompanyStartDate', formatDateField('[name="changed_company_start_date"]', '待填写'));
setPreviewValue('formerLegalRepresentative', fieldValue('[name="operator_name"]', '待填写'));
setPreviewValue('changedLegalRepresentative', fieldValue('[name="secondary_operator_name"]', '待填写'));
root.querySelectorAll('[data-entity-organization-signatures]').forEach(function (element) {
element.hidden = formerCompanyDeregistered;
});
root.querySelectorAll('[data-entity-person-signature]').forEach(function (element) {
element.hidden = !formerCompanyDeregistered;
});
root.querySelectorAll('[data-entity-organization-description]').forEach(function (element) {
element.hidden = formerCompanyDeregistered;
});
root.querySelectorAll('[data-entity-person-description]').forEach(function (element) {
element.hidden = !formerCompanyDeregistered;
});
}
if (templateType === 'shared-contract') {
var sharedSubjectInput = root.querySelector('[name="contract_partner_name"]');
setText('[data-shared-subject-label]', sharedSignerIsPerson ? '物流商归属主体(个人实名)' : '物流商归属主体(企业全称)');
sharedSubjectInput.autocomplete = sharedSignerIsPerson ? 'name' : 'organization';
sharedSubjectInput.placeholder = sharedSignerIsPerson ? '填写该个人在 E 签宝实名认证的姓名' : '填写物流商归属企业在 E 签宝认证的全称';
setText('[data-shared-subject-help]', sharedSignerIsPerson ? '由该个人实名签字确认快递归属及结算主体;正文合作方使用上方的我方公司全称。' : '由该企业盖章确认快递归属及结算主体;正文合作方使用上方的我方公司全称。');
setPreviewValue('contractPartnerName', fieldValue('[name="contract_partner_name"]', '待填写'));
setPreviewValue('sharedCourierName', sharedCourierValues().join('、') || '待填写');
setPreviewValue('sharedSignerLabel', sharedSignerIsPerson ? '确认人(个人签字)' : '确认企业');
root.querySelector('[data-shared-organization-signature]').hidden = sharedSignerIsPerson;
var sharedNote = fieldValue('[name="shared_note"]', '');
setPreviewValue('sharedNote', sharedNote || '待填写');
var sharedNotePreview = root.querySelector('[data-preview-shared-note]');
if (sharedNotePreview) {
sharedNotePreview.hidden = !sharedNote;
}
}
if (templateType === 'cooperation-contract') {
var contractNumber = fieldValue('[name="cooperation_contract_number"]', '');
setPreviewValue('cooperationContractNumber', contractNumber);
root.querySelector('[data-preview-contract-number]').hidden = !contractNumber;
setPreviewValue('cooperationPartyAName', fieldValue('[name="cooperation_party_a_name"]', companyName));
setPreviewValue('cooperationPartyAPhone', fieldValue('[name="cooperation_party_a_phone"]', '待填写'));
setPreviewValue('cooperationPartyBName', fieldValue('[name="cooperation_party_b_name"]', courier === '快递公司' ? '待填写' : courier));
setPreviewValue('cooperationPartyBPhone', fieldValue('[name="cooperation_party_b_phone"]', '待填写'));
setPreviewValue('cooperationStartDate', formatDateField('[name="cooperation_start_date"]', '待填写'));
setPreviewValue('cooperationEndDate', formatDateField('[name="cooperation_end_date"]', '待填写'));
if (supplierContract) {
var supplierValues = {
party_a: fieldValue('[name="cooperation_party_a_name"]', companyName),
party_b: fieldValue('[name="cooperation_party_b_name"]', ''),
party_a_phone: fieldValue('[name="cooperation_party_a_phone"]', ''),
party_b_phone: fieldValue('[name="cooperation_party_b_phone"]', ''),
party_a_signer: fieldValue('[name="secondary_operator_name"]', ''),
party_b_signer: otherSignerIsPerson ? fieldValue('[name="cooperation_party_b_name"]', '') : fieldValue('[name="operator_name"]', ''),
signature_date: formatDateField('[name="signature_date"]', ''),
start_date: formatDateField('[name="cooperation_start_date"]', ''),
end_date: formatDateField('[name="cooperation_end_date"]', '')
};
root.querySelectorAll('[data-supplier-field]').forEach(function (input) { supplierValues[input.dataset.supplierField] = input.value.trim(); });
root.querySelectorAll('[data-supplier-bind]').forEach(function (element) {
var value = supplierValues[element.dataset.supplierBind] || '';
element.textContent = value || '待填写';
element.classList.toggle('is-empty', !value);
});
}
}
if (templateType === 'authorization') {
setPreviewValue('principalName', fieldValue('[name="principal_name"]', '待填写'));
setPreviewValue('principalIdNumber', fieldValue('[name="principal_id_number"]', '待填写'));
setPreviewValue('trusteeName', fieldValue('[name="trustee_name"]', '待填写'));
setPreviewValue('trusteeIdNumber', fieldValue('[name="trustee_id_number"]', '待填写'));
setPreviewValue('authorizationItemNumbers', authorizationItemNumbers(templateType));
setPreviewValue('billCounterparty', fieldValue('[name="bill_counterparty"]', companyName));
setPreviewValue('loanCounterparty', fieldValue('[name="loan_counterparty"]', companyName));
setPreviewValue('paymentCounterparty', fieldValue('[name="payment_counterparty"]', companyName));
setPreviewValue('authorizationStartDate', formatDateField('[name="authorization_start_date"]', '待填写'));
setPreviewValue('authorizationEndDate', formatDateField('[name="authorization_end_date"]', '待填写'));
} else {
authorizationItemNumbers(templateType);
}
if (templateType === 'quote-confirmation') {
var quoteOption = quoteVersionOption();
setPreviewValue('quoteVersion', quoteOption ? quoteOption.textContent.trim().split(' · ')[0] : '待选择');
setPreviewValue('quoteCarrier', quoteOption ? quoteOption.dataset.carrier : courier);
setPreviewValue('quoteType', quoteOption ? quoteOption.dataset.quoteType : '待选择');
setPreviewValue('quotePartyA', companyName);
setPreviewValue('quotePartyB', quoteOption ? quoteOption.dataset.carrier : courier);
setPreviewValue('quoteEffectiveDate', quoteOption ? quoteOption.dataset.effectiveDate : '待选择');
}
}
accountSignerTypeInputs.forEach(function (input) {
input.addEventListener('change', refreshPreview);
});
authorizationSecondarySignerTypeInputs.forEach(function (input) {
input.addEventListener('change', refreshPreview);
});
if (entityChangeDeregisteredInput) {
entityChangeDeregisteredInput.addEventListener('change', refreshPreview);
}
if (accountOrganizationInput) {
accountOrganizationInput.addEventListener('input', function () {
var selectedType = accountSignerTypeInputs.find(function (input) {
return input.checked;
});
if (selectedType && selectedType.value === 'person' && operatorNameInput) {
operatorNameInput.value = accountOrganizationInput.value;
}
});
}
tabs.forEach(function (tab, index) {
tab.addEventListener('click', function () {
showTab(tab.dataset.agreementTab);
});
tab.addEventListener('keydown', function (event) {
if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') {
return;
}
event.preventDefault();
var direction = event.key === 'ArrowRight' ? 1 : -1;
var nextIndex = (index + direction + tabs.length) % tabs.length;
showTab(tabs[nextIndex].dataset.agreementTab, { focus: true });
});
});
root.querySelectorAll('[data-subject-manage-open]').forEach(function (button) {
button.addEventListener('click', function () {
openSubjectModal();
});
});
root.querySelectorAll('[data-subject-modal-close]').forEach(function (button) {
button.addEventListener('click', closeSubjectModal);
});
if (subjectList) {
subjectList.addEventListener('click', async function (event) {
var deleteButton = event.target.closest('[data-subject-delete]');
if (deleteButton) {
subjectDeleteTarget = subjects.find(function (subject) {
return String(subject.id) === deleteButton.dataset.subjectDelete;
});
if (!subjectDeleteTarget) return;
subjectDeletePanel.querySelector('[data-subject-delete-name]').textContent = subjectDeleteTarget.name;
subjectDeletePanel.querySelector('[data-subject-delete-hint]').textContent = subjects.length === 1
? '删除后将使用当前公司作为签署主体。'
: (subjectDeleteTarget.is_default ? '删除后将自动选择剩余主体作为默认主体。' : '');
subjectDeletePanel.querySelector('[data-subject-delete-error]').textContent = '';
subjectDeletePanel.hidden = false;
subjectDeletePanel.querySelector('[data-subject-delete-cancel]').focus();
return;
}
var editButton = event.target.closest('[data-subject-edit]');
if (editButton) {
openSubjectModal(editButton.dataset.subjectEdit);
return;
}
var defaultButton = event.target.closest('[data-subject-default]');
if (!defaultButton) {
return;
}
defaultButton.disabled = true;
defaultButton.textContent = '切换中…';
try {
var payload = await requestSubject(subjectUrl(subjectForm.dataset.defaultUrlTemplate, defaultButton.dataset.subjectDefault));
subjects = payload.subjects || subjects;
renderSubjectList();
renderSubjectSelect(defaultButton.dataset.subjectDefault);
var selectedOption = subjectSelect && subjectSelect.options[subjectSelect.selectedIndex];
syncSubjectLinkedNames(selectedOption && selectedOption.value);
refreshPreview();
announce(payload.message || '默认签署主体已切换');
} catch (error) {
subjectFormError.textContent = error.message;
} finally {
defaultButton.disabled = false;
}
});
}
subjectDeletePanel.querySelector('[data-subject-delete-cancel]').addEventListener('click', function () {
var targetId = subjectDeleteTarget && String(subjectDeleteTarget.id);
closeSubjectDelete();
var trigger = subjectList.querySelector('[data-subject-delete="' + targetId + '"]');
if (trigger) trigger.focus();
});
subjectDeletePanel.querySelector('[data-subject-delete-confirm]').addEventListener('click', async function () {
if (!subjectDeleteTarget) return;
var deletedId = String(subjectDeleteTarget.id);
var confirmButton = subjectDeletePanel.querySelector('[data-subject-delete-confirm]');
var cancelButton = subjectDeletePanel.querySelector('[data-subject-delete-cancel]');
var errorElement = subjectDeletePanel.querySelector('[data-subject-delete-error]');
var body = new FormData();
body.append('_token', subjectForm.querySelector('[name="_token"]').value);
body.append('_method', 'DELETE');
body.append('delete_confirmed', '1');
confirmButton.disabled = cancelButton.disabled = true;
confirmButton.textContent = '删除中…';
errorElement.textContent = '';
try {
var payload = await requestSubject(subjectUrl(subjectForm.dataset.deleteUrlTemplate, deletedId), body);
subjects = payload.subjects;
if (subjectIdInput.value === deletedId) resetSubjectForm();
renderSubjectList();
renderSubjectSelect();
var selectedOption = subjectSelect && subjectSelect.options[subjectSelect.selectedIndex];
syncSubjectLinkedNames(selectedOption && selectedOption.value);
refreshPreview();
closeSubjectDelete();
subjectNameInput.focus();
announce(payload.message || '公司主体已删除');
} catch (error) {
errorElement.textContent = error.message;
} finally {
confirmButton.disabled = cancelButton.disabled = false;
confirmButton.textContent = '确认删除';
}
});
if (subjectFormCancel) {
subjectFormCancel.addEventListener('click', resetSubjectForm);
}
if (subjectForm) {
subjectForm.addEventListener('submit', async function (event) {
event.preventDefault();
subjectFormError.textContent = '';
if (!subjectForm.checkValidity()) {
subjectForm.reportValidity();
return;
}
var subjectId = subjectIdInput.value;
var url = subjectId
? subjectUrl(subjectForm.dataset.updateUrlTemplate, subjectId)
: subjectForm.dataset.storeUrl;
subjectFormSubmit.disabled = true;
subjectFormSubmit.querySelector('span:last-child').textContent = '保存中…';
try {
var payload = await requestSubject(url, new FormData(subjectForm));
subjects = payload.subjects || subjects;
renderSubjectList();
renderSubjectSelect(payload.subject && payload.subject.id);
if (payload.subject && subjectSelect) {
subjectSelect.value = payload.subject.name;
syncSubjectLinkedNames(payload.subject.name);
refreshPreview();
}
closeSubjectModal();
announce(payload.message || '公司主体已保存');
} catch (error) {
subjectFormError.textContent = error.message;
} finally {
subjectFormSubmit.disabled = false;
subjectFormSubmit.querySelector('span:last-child').textContent = '保存主体';
}
});
}
if (subjectSelect) {
subjectSelect.addEventListener('change', function () {
var option = subjectSelect.options[subjectSelect.selectedIndex];
if (option && !option.dataset.subjectFallback) {
syncSubjectLinkedNames(option.value);
}
refreshPreview();
});
}
if (courierSelect) {
courierSelect.addEventListener('change', function () {
if (courierSearch) {
courierSearch.value = courierSelect.value;
syncCourierSelection();
}
syncEsignAccount();
refreshPreview();
});
}
if (sharedCourierAdd) {
sharedCourierAdd.addEventListener('click', addSharedCourier);
}
if (sharedCourierList) {
sharedCourierList.addEventListener('click', function (event) {
var remove = event.target.closest('[data-shared-courier-remove]');
if (!remove || remove.disabled) {
return;
}
var row = remove.closest('.agreement-shared-courier-row');
if (row) {
row.remove();
updateSharedCourierRemoveButtons();
refreshPreview();
}
});
sharedCourierList.addEventListener('input', refreshPreview);
sharedCourierList.addEventListener('change', refreshPreview);
updateSharedCourierRemoveButtons();
}
if (quoteVersionSelect) {
quoteVersionSelect.addEventListener('change', function () {
var option = quoteVersionOption();
if (option && courierSelect && option.dataset.carrier) {
var courierOption = Array.prototype.slice.call(courierSelect.options).find(function (item) {
return item.value === option.dataset.carrier;
});
if (courierOption) {
courierSelect.value = option.dataset.carrier;
if (courierSearch) {
courierSearch.value = option.dataset.carrier;
syncCourierSelection();
}
syncEsignAccount();
}
}
refreshPreview();
loadQuotePreview();
});
}
if (esignAccountInput) {
esignAccountInput.addEventListener('input', function () {
delete esignAccountInput.dataset.autoFilled;
});
}
root.querySelector('[data-request-cancel]').addEventListener('click', function () {
showTab('tasks');
});
root.querySelector('[data-preview-refresh]').addEventListener('click', function () {
refreshPreview();
if (selectedDocument().value === 'quote-confirmation') {
loadQuotePreview();
}
announce('协议预览已刷新');
});
partnerTypeInputs.forEach(function (input) {
input.addEventListener('change', function () {
syncPartnerType();
refreshPreview();
announce(currentPartnerType === 'supplier' ? '已切换到供应商' : '已切换到快递公司');
});
});
form.querySelectorAll('input, select, textarea').forEach(function (control) {
control.addEventListener('input', refreshPreview);
control.addEventListener('change', refreshPreview);
});
form.addEventListener('submit', function (event) {
refreshPreview();
if (!form.checkValidity()) {
event.preventDefault();
var error = root.querySelector('[data-request-error]');
if (error) {
error.textContent = '请先补齐当前文件类型所需字段,并确认签署账号有效。';
}
announce('协议字段未填写完整');
return;
}
var submit = root.querySelector('[data-sign-request-send]');
if (submit) {
submit.disabled = true;
submit.setAttribute('aria-busy', 'true');
submit.querySelector('span:last-child').textContent = '正在推送…';
}
});
window.addEventListener('popstate', function () {
var url = new URL(window.location.href);
var view = url.searchParams.get('agreement_view') || 'tasks';
showTab(view, { updateUrl: false });
loadTasks(url, { updateUrl: false });
});
window.addEventListener('keydown', function (event) {
if (!deleteTaskModal.hidden) {
if (event.key === 'Escape') {
closeDeleteTaskModal();
} else if (event.key === 'Tab') {
var deleteControls = Array.prototype.filter.call(deleteTaskModal.querySelectorAll('button'), function (control) { return !control.disabled; });
if (deleteControls.length === 0) {
event.preventDefault();
} else if (event.shiftKey && document.activeElement === deleteControls[0]) {
event.preventDefault();
deleteControls[deleteControls.length - 1].focus();
} else if (!event.shiftKey && document.activeElement === deleteControls[deleteControls.length - 1]) {
event.preventDefault();
deleteControls[0].focus();
}
}
return;
}
if (!archiveModal.hidden) {
if (event.key === 'Escape') {
closeArchiveModal();
} else if (event.key === 'Tab') {
var controls = Array.prototype.filter.call(archiveModal.querySelectorAll('button, input, textarea'), function (control) {
return !control.disabled && (control.type !== 'radio' || control.checked);
});
var first = controls[0];
var last = controls[controls.length - 1];
if (event.shiftKey && document.activeElement === first) {
event.preventDefault();
last.focus();
} else if (!event.shiftKey && document.activeElement === last) {
event.preventDefault();
first.focus();
}
}
return;
}
if (event.key === 'Escape' && subjectModal && !subjectModal.hidden) {
closeSubjectModal();
}
});
var initialUrl = new URL(window.location.href);
var initialView = initialUrl.searchParams.get('agreement_view') || 'tasks';
initializeCourierSearch();
syncPartnerType();
renderSubjectSelect();
renderSubjectList();
showTab(initialView, { updateUrl: false });
syncEsignAccount();
refreshPreview();
// 快递资料「打款信息新增 / 变更」跳过来:预填快递、文件类型和账户信息,提示补齐后推送。
var paymentPrefill = @json($agreementPaymentPrefill);
if (paymentPrefill) {
showTab('create', { updateUrl: false });
var courierPartner = root.querySelector('[data-partner-type][value="courier"]');
if (courierPartner && !courierPartner.checked) {
courierPartner.checked = true;
courierPartner.dispatchEvent(new Event('change', { bubbles: true }));
}
if (courierSelect && paymentPrefill.courier_name) {
var prefillOption = Array.prototype.find.call(courierSelect.options, function (option) { return option.value === paymentPrefill.courier_name; });
if (!prefillOption) {
prefillOption = new Option(paymentPrefill.courier_name, paymentPrefill.courier_name);
courierSelect.appendChild(prefillOption);
courierOptions.push({ value: paymentPrefill.courier_name, account: paymentPrefill.esign_account || '' });
}
if (paymentPrefill.esign_account && !prefillOption.dataset.esignAccount) {
prefillOption.dataset.esignAccount = paymentPrefill.esign_account;
}
courierSelect.value = paymentPrefill.courier_name;
courierSelect.dispatchEvent(new Event('change', { bubbles: true }));
}
documentSelect.value = paymentPrefill.document_type;
documentSelect.dispatchEvent(new Event('change', { bubbles: true }));
var prefillSigner = form.querySelector('[name="counterparty_signer_type"][value="' + paymentPrefill.signer_type + '"]');
if (prefillSigner) {
prefillSigner.checked = true;
prefillSigner.dispatchEvent(new Event('change', { bubbles: true }));
}
Object.keys(paymentPrefill.fields || {}).forEach(function (name) {
var input = form.querySelector('[name="' + name + '"]');
if (input) {
input.value = paymentPrefill.fields[name];
input.dispatchEvent(new Event('input', { bubbles: true }));
}
});
refreshPreview();
if (announcer) announcer.textContent = '已按快递资料的打款信息预填协议,请补齐签署人信息后推送。';
}
if (initialUrl.searchParams.has('agreement_step')) {
updateUrl(initialView, true);
}
})();
</script>
</section>