3960 lines
225 KiB
PHP
3960 lines
225 KiB
PHP
@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($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
|
||
<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" 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">
|
||
<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>
|
||
|
||
<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>
|
||
|
||
<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">
|
||
<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.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') {
|
||
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();
|
||
|
||
if (initialUrl.searchParams.has('agreement_step')) {
|
||
updateUrl(initialView, true);
|
||
}
|
||
})();
|
||
</script>
|
||
</section>
|