CaiWuXiTong/resources/views/business/pages/courier-payables/courier-onboarding-show.blade.php

482 lines
48 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

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

@php
/** @var \App\Models\Business\CourierOnboarding $onboarding */
$status = $onboarding->status;
$expired = $onboarding->linkExpired() && in_array($status, ['invited', 'returned'], true);
$badge = match ($status) {
'submitted', 'first_approved', 'approved' => 'is-pending',
'returned' => 'is-warning',
'activated' => 'is-success',
'rejected', 'cancelled' => 'is-muted',
default => 'is-info',
};
$show = static fn ($value): string => filled($value) ? (string) $value : '—';
$num = static fn ($v): string => $v === null || $v === '' ? '—' : rtrim(rtrim(number_format((float) $v, 4, '.', ''), '0'), '.');
$quoteColumns = $onboarding->quoteColumns();
$quoteRows = $onboarding->quoteRowList();
$quoteSheet = $onboarding->files->where('kind', \App\Models\Business\CourierOnboardingFile::QUOTE_SHEET_KIND)->last();
$quoteUrl = route('business.pages.show', ['section' => 'courier-payables', 'page' => 'quote-management']);
@endphp
<x-layouts.admin>
<x-slot name="title">快递入驻 {{ $onboarding->number }}</x-slot>
<x-slot name="content">
<style>
.cod { --ink:var(--vip-content-ink,#171717); --muted:var(--vip-content-muted,#595959); --gold:var(--vip-content-accent-dark,#856632); --soft:var(--vip-content-accent-soft,#F7F0DE); --line:var(--vip-border,#D8D2C7); margin:24px 40px; color:var(--ink); font-family:"JetBrains Mono","Microsoft YaHei","PingFang SC",monospace; font-size:13px; }
.cod * { box-sizing:border-box; }
.cod__toolbar { display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:12px; margin-bottom:16px; }
.cod__back { display:inline-flex; align-items:center; gap:5px; color:var(--gold); font-size:12px; text-decoration:none; }
.cod__heading { display:flex; align-items:center; flex-wrap:wrap; gap:10px; margin:6px 0 0; font-size:18px; font-weight:700; }
.cod__heading small { color:var(--muted); font-size:12px; font-weight:500; font-variant-numeric:tabular-nums; }
.cod__badge { display:inline-flex; align-items:center; padding:3px 10px; border-radius:999px; font-size:12px; font-weight:700; }
.cod__badge.is-pending { background:#fff4df; color:#935f07; } .cod__badge.is-warning { background:#fde9d4; color:#8a4a06; } .cod__badge.is-success { background:#edf5e8; color:#53793e; } .cod__badge.is-muted { background:#f1efea; color:#595959; } .cod__badge.is-info { background:#e8f2f8; color:#006395; }
.cod__layout { display:grid; grid-template-columns:minmax(0,1fr) 360px; gap:16px; align-items:start; }
.cod__main, .cod__side { display:grid; gap:16px; min-width:0; }
.cod__side { position:sticky; top:16px; }
.cod__panel { overflow:hidden; border:1px solid var(--line); border-radius:8px; background:#fff; }
.cod__panel-head { display:flex; align-items:center; justify-content:space-between; gap:8px; padding:12px 16px; border-bottom:1px solid var(--line); }
.cod__panel-title { display:flex; align-items:center; gap:8px; margin:0; font-size:14px; font-weight:600; }
.cod__panel-title .material-icons-outlined { color:var(--gold); font-size:19px; }
.cod__panel-body { padding:16px; }
.cod__meta { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:14px 18px; margin:0; }
.cod__meta dt { color:var(--muted); font-size:11px; }
.cod__meta dd { margin:4px 0 0; font-size:12.5px; word-break:break-all; font-variant-numeric:tabular-nums; }
.cod__meta .is-wide { grid-column:span 3; }
.cod__alert { display:flex; align-items:flex-start; gap:8px; margin-bottom:16px; padding:10px 12px; border:1px solid #D9BD88; border-radius:8px; background:#FFF8E8; color:#704800; font-size:12px; line-height:1.6; }
.cod__alert.is-success { border-color:#b7cda8; background:#f1f7ec; color:#2f4a22; }
.cod__alert.is-error { border-color:#e3b0b0; background:#fdf1f1; color:#7a1010; }
.cod__alert .material-icons-outlined { flex:none; font-size:18px; }
.cod__alert ul { margin:4px 0 0; padding-left:18px; }
.cod__button { display:inline-flex; align-items:center; justify-content:center; gap:6px; height:34px; padding:0 14px; border:1px solid var(--line); border-radius:8px; background:#fff; color:var(--ink); font:inherit; font-weight:500; text-decoration:none; white-space:nowrap; cursor:pointer; }
.cod__button--primary { border-color:var(--gold); background:var(--gold); color:#fff; } .cod__button--primary:hover { background:#6A5129; }
.cod__button--danger { border-color:#B80000; color:#8A1515; }
.cod__button .material-icons-outlined { font-size:17px; }
.cod__button[disabled] { cursor:not-allowed; opacity:.55; }
.cod__stack { display:grid; gap:10px; }
.cod__row { display:flex; flex-wrap:wrap; gap:8px; }
.cod__field { display:grid; gap:5px; } .cod__field label { color:var(--muted); font-size:11px; font-weight:600; }
.cod__field input, .cod__field textarea, .cod__field select { width:100%; min-height:34px; padding:6px 10px; border:1px solid var(--line); border-radius:8px; background:#fff; color:var(--ink); font:inherit; }
.cod__field textarea { min-height:64px; resize:vertical; }
.cod__field input:focus, .cod__field textarea:focus { border-color:var(--gold); outline:none; box-shadow:0 0 0 3px rgba(133,102,50,.18); }
.cod__help { color:var(--muted); font-size:11px; line-height:1.55; }
.cod__divider { height:1px; margin:4px 0; background:var(--line); }
.cod__qr { display:grid; justify-items:center; gap:10px; }
.cod__qr img { width:220px; height:220px; border:1px solid var(--line); border-radius:8px; image-rendering:pixelated; }
.cod__link { display:flex; gap:6px; width:100%; }
.cod__link input { flex:1; min-width:0; height:34px; padding:0 8px; border:1px solid var(--line); border-radius:8px; background:#fffdf8; color:var(--muted); font:inherit; font-size:11px; }
.cod table { width:100%; border-collapse:collapse; font-size:12.5px; }
.cod th { padding:9px 12px; border-bottom:1px solid var(--line); background:var(--soft); font-size:12px; font-weight:600; text-align:left; white-space:nowrap; }
.cod td { padding:8px 12px; border-bottom:1px solid #ECE8E0; }
.cod tbody tr:last-child td { border-bottom:0; }
.cod .is-number { text-align:right; font-variant-numeric:tabular-nums; }
.cod__files { display:grid; grid-template-columns:repeat(auto-fill,minmax(150px,1fr)); gap:10px; }
.cod__file { display:grid; gap:6px; padding:8px; border:1px solid var(--line); border-radius:8px; background:#fffdf8; color:var(--ink); text-decoration:none; }
.cod__file-thumb { display:grid; height:96px; place-items:center; overflow:hidden; border-radius:6px; background:#f1ede4; color:var(--gold); }
.cod__file-thumb img { width:100%; height:100%; object-fit:cover; }
.cod__file-kind { color:var(--gold); font-size:11px; font-weight:700; }
.cod__file-name { overflow:hidden; font-size:11.5px; text-overflow:ellipsis; white-space:nowrap; }
.cod__file-size { color:var(--muted); font-size:10.5px; }
.cod__timeline { display:grid; }
.cod__event { position:relative; display:grid; grid-template-columns:120px 1fr; gap:14px; padding:0 0 16px 22px; }
.cod__event::before { position:absolute; top:4px; bottom:-4px; left:6px; width:1px; background:var(--line); content:''; }
.cod__event::after { position:absolute; top:4px; left:2px; width:9px; height:9px; border:2px solid var(--gold); border-radius:50%; background:#fff; content:''; }
.cod__event:last-child::before { display:none; }
.cod__event-time { color:var(--muted); font-size:11px; font-variant-numeric:tabular-nums; }
.cod__event-title { font-weight:600; }
.cod__event-note { margin-top:3px; color:var(--muted); font-size:12px; white-space:pre-wrap; }
details.cod__more summary { color:var(--gold); cursor:pointer; font-size:12px; }
details.cod__more[open] summary { margin-bottom:10px; }
@media (max-width:1200px) { .cod { margin:16px; } .cod__layout { grid-template-columns:1fr; } .cod__side { position:static; } .cod__meta { grid-template-columns:repeat(2,minmax(0,1fr)); } .cod__meta .is-wide { grid-column:span 2; } }
</style>
<div class="cod">
<div class="cod__toolbar">
<div>
<a class="cod__back" href="{{ route('business.pages.show', ['section' => 'courier-payables', 'page' => 'courier-onboarding']) }}"><span class="material-icons-outlined" aria-hidden="true" style="font-size:16px">arrow_back</span>返回快递入驻</a>
<h1 class="cod__heading">{{ $onboarding->displayName() }}<span class="cod__badge {{ $badge }}">{{ $expired ? '链接已过期' : $onboarding->statusLabel() }}</span><small>{{ $onboarding->number }}</small></h1>
</div>
</div>
@if (session('success'))
<div class="cod__alert is-success" role="status"><span class="material-icons-outlined" aria-hidden="true">check_circle</span><span>{{ session('success') }}</span></div>
@endif
@if ($errors->any())
<div class="cod__alert is-error" role="alert"><span class="material-icons-outlined" aria-hidden="true">error_outline</span><div>操作未完成<ul>@foreach ($errors->all() as $message)<li>{{ $message }}</li>@endforeach</ul></div></div>
@endif
@if ($status === 'returned' && $onboarding->return_reason)
<div class="cod__alert" role="status"><span class="material-icons-outlined" aria-hidden="true">assignment_return</span><span>已退回补件:{{ $onboarding->return_reason }}</span></div>
@endif
<div class="cod__layout">
<div class="cod__main">
@if (in_array($status, ['invited', 'returned'], true) && blank($onboarding->company_full_name))
<div class="cod__panel"><div class="cod__panel-body cod__help">快递方还没有填写资料。把右侧二维码发给对方,扫码后即可在手机上填写;填写过程中可以随时暂存。</div></div>
@endif
<section class="cod__panel" aria-labelledby="cod-company">
<div class="cod__panel-head"><h2 class="cod__panel-title" id="cod-company"><span class="material-icons-outlined" aria-hidden="true">{{ $onboarding->isPerson() ? 'person' : 'apartment' }}</span>入驻主体与联系人</h2><span class="cod__badge {{ $onboarding->isPerson() ? 'is-warning' : 'is-info' }}">{{ $onboarding->entityLabel() }}入驻</span></div>
<div class="cod__panel-body">
<dl class="cod__meta">
<div class="is-wide"><dt>{{ $onboarding->subjectLabel() }}</dt><dd>{{ $show($onboarding->company_full_name) }}</dd></div>
@if ($onboarding->isPerson())
<div><dt>身份证号</dt><dd>{{ $show($onboarding->maskedIdNumber()) }}</dd></div>
@else
<div><dt>统一社会信用代码</dt><dd>{{ $show($onboarding->unified_social_credit_code) }}</dd></div>
<div><dt>法定代表人</dt><dd>{{ $show($onboarding->legal_representative) }}</dd></div>
@endif
<div><dt>快递品牌 / 业务类型</dt><dd>{{ $show($onboarding->carrier_brand) }} · {{ $show($onboarding->service_type) }}</dd></div>
<div><dt>网点名称</dt><dd>{{ $show($onboarding->network_name) }}</dd></div>
<div class="is-wide" style="grid-column:span 2"><dt>经营地址</dt><dd>{{ $show($onboarding->business_address) }}</dd></div>
<div><dt>业务对接人</dt><dd>{{ $show($onboarding->contact_name) }} {{ $onboarding->contact_phone }}</dd></div>
<div><dt>财务对账人</dt><dd>{{ $show($onboarding->finance_contact_name) }} {{ $onboarding->finance_contact_phone }}</dd></div>
<div><dt>e签宝签署人</dt><dd>{{ $show($onboarding->esign_operator_name) }} {{ $onboarding->esign_account }}</dd></div>
<div><dt>提交时间</dt><dd>{{ $onboarding->submitted_at?->format('Y-m-d H:i') ?? '—' }}</dd></div>
<div class="is-wide"><dt>可揽收仓库 / 区域</dt><dd>{{ $show($onboarding->pickup_warehouses) }}</dd></div>
</dl>
</div>
</section>
<section class="cod__panel" aria-labelledby="cod-settle">
<div class="cod__panel-head"><h2 class="cod__panel-title" id="cod-settle"><span class="material-icons-outlined" aria-hidden="true">account_balance</span>结算与开票</h2></div>
<div class="cod__panel-body">
@php
$accountChecks = $onboarding->accountChecks();
$checkBadge = static fn (?bool $ok, string $okText, string $badText): string => $ok === null ? '' : '<span style="margin-left:6px;font-size:12px;color:' . ($ok ? '#2F6B2A' : '#A1281F') . '">' . e($ok ? '✓ ' . $okText : '✗ ' . $badText) . '</span>';
@endphp
<dl class="cod__meta">
<div><dt>对公户名</dt><dd>{{ $show($onboarding->bank_account_name) }}{!! $checkBadge($accountChecks['corporate'], '与营业执照公司全称一致', '与公司全称不一致') !!}</dd></div>
<div><dt>对公开户行</dt><dd>{{ $show($onboarding->bank_name) }}</dd></div>
<div><dt>对公账号</dt><dd>{{ $show($onboarding->bank_account_number) }}</dd></div>
<div><dt>对私收款人</dt><dd>{{ $show($onboarding->private_account_name) }}{!! $checkBadge($accountChecks['private'], $onboarding->isPerson() ? '与本人姓名一致' : '与法定代表人一致', $onboarding->isPerson() ? '与本人姓名不一致' : '与法定代表人不一致') !!}</dd></div>
<div><dt>对私开户行</dt><dd>{{ $show($onboarding->private_bank_name) }}</dd></div>
<div><dt>对私卡号</dt><dd>{{ $show($onboarding->private_account_number) }}</dd></div>
<div><dt>开票类型</dt><dd>{{ $show($onboarding->invoice_type) }}</dd></div>
<div><dt>税率</dt><dd>{{ $onboarding->tax_rate !== null ? $num($onboarding->tax_rate) . '%' : '—' }}</dd></div>
<div><dt>结算周期</dt><dd>{{ $show($onboarding->settlement_cycle) }}</dd></div>
</dl>
<p class="cod__help" style="margin:12px 0 0">核对依据:快递填写的营业执照公司全称 / 法定代表人{{ $onboarding->isPerson() ? '(个人入驻为本人姓名)' : '' }}。请对照下方营业执照、身份证和银行卡照片确认填写无误。</p>
</div>
</section>
<section class="cod__panel" aria-labelledby="cod-quote">
<div class="cod__panel-head">
<h2 class="cod__panel-title" id="cod-quote"><span class="material-icons-outlined" aria-hidden="true">request_quote</span>{{ $quoteVersions->count() > 1 ? "入驻首版报价" : "报价" }}</h2>
@if ($onboarding->quoteVersion)
<a class="cod__button" href="{{ $quoteUrl }}"><span class="material-icons-outlined" aria-hidden="true">open_in_new</span>报价管理 {{ $onboarding->quoteVersion->version_code }}</a>
@endif
</div>
<div class="cod__panel-body">
<dl class="cod__meta" style="margin-bottom:14px">
<div><dt>计费方式</dt><dd><strong>{{ $show($onboarding->quoteModeLabel()) }}</strong></dd></div>
<div><dt>执行日期</dt><dd>{{ $onboarding->quote_effective_date?->format('Y-m-d') ?? '—' }}</dd></div>
<div><dt>重量取整</dt><dd>{{ \App\Support\CourierQuoteStructure::ROUNDING[$onboarding->weight_rounding ?? 'none'] ?? '不取整' }}</dd></div>
<div class="is-wide"><dt>计费规则</dt><dd>@foreach ($onboarding->quoteRuleLines() as $rule)<div>{{ $rule }}</div>@endforeach</dd></div>
<div class="is-wide"><dt>报价备注</dt><dd>{{ $show($onboarding->quote_note) }}</dd></div>
</dl>
@if ($onboarding->quote_mode === 'other')
<div class="cod__alert" style="margin:0"><span class="material-icons-outlined" aria-hidden="true">upload_file</span><span>特殊计费,快递上传了报价表{{ $quoteSheet ? ':' . $quoteSheet->original_name : '' }}。复审通过后请在「报价管理」里按报价表录入首版报价,再发起报价确认。</span></div>
@if ($quoteSheet)<p style="margin:10px 0 0"><a class="cod__button" href="{{ route('business.courier-onboardings.file', [$onboarding, $quoteSheet]) }}?download=1"><span class="material-icons-outlined" aria-hidden="true">download</span>下载报价表</a></p>@endif
@elseif ($quoteRows === [])
<p class="cod__help">快递方还没有填写报价明细。</p>
@else
<div style="overflow-x:auto">
<table aria-label="报价明细">
<thead><tr><th>省份 / 区域</th>@foreach ($quoteColumns as $column)<th class="is-number">{{ $column['label'] }}</th>@endforeach</tr></thead>
<tbody>
@foreach ($quoteRows as $row)
<tr><td>{{ $row['region'] }}</td>@foreach (\App\Support\CourierQuoteStructure::rowValues($row, $quoteColumns) as $cell)<td class="is-number">{{ $num($cell) }}</td>@endforeach</tr>
@endforeach
</tbody>
</table>
</div>
<p class="cod__help" style="margin:10px 0 0">共 {{ count($quoteRows) }} 个地区。复审通过后这份报价会作为首版报价写进报价管理,并生成报价确认单推送 e签宝。</p>
@endif
</div>
</section>
<section class="cod__panel" aria-labelledby="cod-files">
<div class="cod__panel-head"><h2 class="cod__panel-title" id="cod-files"><span class="material-icons-outlined" aria-hidden="true">attach_file</span>资料附件</h2><span class="cod__help">{{ $onboarding->files->count() }} 个</span></div>
<div class="cod__panel-body">
@if ($onboarding->files->isEmpty())
<p class="cod__help">暂未上传附件。</p>
@else
<div class="cod__files">
@foreach ($onboarding->files as $file)
@php $fileUrl = route('business.courier-onboardings.file', [$onboarding, $file]); @endphp
<a class="cod__file" href="{{ $fileUrl }}" target="_blank" rel="noopener">
<span class="cod__file-thumb">
@if ($file->isImage())
<img src="{{ $fileUrl }}" alt="{{ \App\Models\Business\CourierOnboardingFile::labelFor($file->kind, $onboarding->entity_type) }}" loading="lazy">
@else
<span class="material-icons-outlined" aria-hidden="true" style="font-size:34px">description</span>
@endif
</span>
<span class="cod__file-kind">{{ \App\Models\Business\CourierOnboardingFile::labelFor($file->kind, $onboarding->entity_type) }}</span>
<span class="cod__file-name" title="{{ $file->original_name }}">{{ $file->original_name }}</span>
<span class="cod__file-size">{{ $file->sizeLabel() }} · {{ $file->created_at?->format('m-d H:i') }}</span>
</a>
@endforeach
</div>
@endif
</div>
</section>
<section class="cod__panel" aria-labelledby="cod-timeline">
<div class="cod__panel-head"><h2 class="cod__panel-title" id="cod-timeline"><span class="material-icons-outlined" aria-hidden="true">history</span>处理记录</h2></div>
<div class="cod__panel-body">
<div class="cod__timeline">
@foreach ($onboarding->events->sortByDesc('id') as $event)
<div class="cod__event">
<span class="cod__event-time">{{ $event->created_at?->format('Y-m-d H:i') }}</span>
<div><div class="cod__event-title">{{ $event->eventLabel() }} · {{ $event->actorLabel() }}</div>@if ($event->note)<div class="cod__event-note">{{ $event->note }}</div>@endif</div>
</div>
@endforeach
</div>
</div>
</section>
</div>
<aside class="cod__side">
<section class="cod__panel" aria-label="指定审核人员">
<div class="cod__panel-head"><h2 class="cod__panel-title">指定审核人员</h2></div>
<div class="cod__panel-body cod__stack">
<p class="cod__help" style="margin:0">初审:{{ implode('、', array_column($reviewerSettings['first'], 'display_name')) ?: '尚未配置' }}</p>
<p class="cod__help" style="margin:0">复审:{{ implode('、', array_column($reviewerSettings['final'], 'display_name')) ?: '尚未配置' }}</p>
<p class="cod__help" style="margin:0">各环节任意一人通过即可,初审与复审须由不同人员完成。</p>
@if ($isAdmin)<a class="cod__button" href="{{ route('system-settings.workflow-reviewers.index') }}">设置审核人员</a>@endif
</div>
</section>
@if (in_array($status, ['invited', 'returned'], true))
<section class="cod__panel" aria-labelledby="cod-qr">
<div class="cod__panel-head"><h2 class="cod__panel-title" id="cod-qr"><span class="material-icons-outlined" aria-hidden="true">qr_code_2</span>入驻二维码</h2><span class="cod__help">{{ $onboarding->expires_at ? '有效期至 ' . $onboarding->expires_at->format('Y-m-d') : '' }}</span></div>
<div class="cod__panel-body cod__qr">
@if ($expired)
<div class="cod__alert" style="margin:0;width:100%"><span class="material-icons-outlined" aria-hidden="true">schedule</span><span>链接已过期,延期后原二维码即可继续使用。</span></div>
@endif
<img src="{{ route('business.courier-onboardings.qr', $onboarding) }}" alt="快递入驻二维码" width="220" height="220">
<div class="cod__link">
<input type="text" value="{{ $formUrl }}" readonly aria-label="入驻链接" data-copy-source>
<button type="button" class="cod__button" data-copy-button><span class="material-icons-outlined" aria-hidden="true">content_copy</span>复制</button>
</div>
<div class="cod__row">
<a class="cod__button" href="{{ route('business.courier-onboardings.qr', [$onboarding, 'download' => 1]) }}"><span class="material-icons-outlined" aria-hidden="true">download</span>下载二维码</a>
<form method="POST" action="{{ route('business.courier-onboardings.extend', $onboarding) }}">@csrf<button type="submit" class="cod__button"><span class="material-icons-outlined" aria-hidden="true">update</span>延期 30 天</button></form>
</div>
<form method="POST" action="{{ route('business.courier-onboardings.cancel', $onboarding) }}" data-confirm="作废后原二维码将无法打开,确认作废?">@csrf<button type="submit" class="cod__button cod__button--danger"><span class="material-icons-outlined" aria-hidden="true">block</span>作废邀请</button></form>
</div>
</section>
@endif
@if ($status === 'submitted')
<section class="cod__panel" aria-labelledby="cod-first">
<div class="cod__panel-head"><h2 class="cod__panel-title" id="cod-first"><span class="material-icons-outlined" aria-hidden="true">fact_check</span>初审</h2></div>
<div class="cod__panel-body cod__stack">
<p class="cod__help" style="margin:0">核对营业执照、开户证明和盖章报价单是否与填写一致。</p>
@if ($canFirstReview)
<form method="POST" action="{{ route('business.courier-onboardings.first-approve', $onboarding) }}" class="cod__stack">
@csrf
<div class="cod__field"><label for="cod-first-note">初审意见(选填)</label><textarea id="cod-first-note" name="note" maxlength="1000"></textarea></div>
<button type="submit" class="cod__button cod__button--primary"><span class="material-icons-outlined" aria-hidden="true">done</span>初审通过</button>
</form>
@include('business.pages.courier-payables.partials.courier-onboarding-return', ['onboarding' => $onboarding])
@else
<p class="cod__help" style="margin:0">{{ $reviewAccess['message'] }}</p>
@endif
</div>
</section>
@elseif ($status === 'first_approved')
<section class="cod__panel" aria-labelledby="cod-final">
<div class="cod__panel-head"><h2 class="cod__panel-title" id="cod-final"><span class="material-icons-outlined" aria-hidden="true">verified</span>财务复审</h2></div>
<div class="cod__panel-body cod__stack">
@if ($canFinalReview)
<form method="POST" action="{{ route('business.courier-onboardings.final-approve', $onboarding) }}" class="cod__stack">
@csrf
@if ($onboarding->courier_name)
<div class="cod__field">
<label>系统快递名称</label>
<div style="font-size:15px;font-weight:700">{{ $onboarding->courier_name }}</div>
<span class="cod__help">生成二维码时已定好;复审通过后锁定,首版报价和 e签宝报价确认单都用这个名称。如需更正,请先在下方「内部信息」修改。</span>
</div>
@else
<div class="cod__field">
<label for="cod-courier-name">系统快递名称 *</label>
<input id="cod-courier-name" name="courier_name" type="text" maxlength="100" required value="{{ old('courier_name') }}">
<span class="cod__help">必须与报价名、发货数据里的「快递名称」完全一致,复审后不可再改。</span>
</div>
@endif
<div class="cod__field"><label for="cod-reconciler">对账人</label><input id="cod-reconciler" name="reconciler" type="text" maxlength="100" value="{{ old('reconciler', $onboarding->reconciler) }}"></div>
<div class="cod__field"><label for="cod-final-note">复审意见(选填)</label><textarea id="cod-final-note" name="note" maxlength="1000"></textarea></div>
<button type="submit" class="cod__button cod__button--primary"><span class="material-icons-outlined" aria-hidden="true">verified</span>复审通过,生成首版报价</button>
</form>
@include('business.pages.courier-payables.partials.courier-onboarding-return', ['onboarding' => $onboarding])
@else
<p class="cod__help" style="margin:0">{{ $reviewAccess['message'] }}</p>
@endif
</div>
</section>
@elseif ($status === 'approved')
@php
$quoteSigned = $quoteSignature?->status === 'archived';
$canPush = $isAdmin && $esignReady && $onboarding->quoteVersion && (! $quoteSignature || $quoteSignature->canSend());
@endphp
<section class="cod__panel" aria-labelledby="cod-sign">
<div class="cod__panel-head"><h2 class="cod__panel-title" id="cod-sign"><span class="material-icons-outlined" aria-hidden="true">draw</span>报价确认 · 开通</h2></div>
<div class="cod__panel-body cod__stack">
<dl class="cod__meta" style="grid-template-columns:1fr 1fr">
<div><dt>报价确认单</dt><dd>{{ $onboarding->quoteVersion?->version_code ?? '—' }}</dd></div>
<div><dt>e签宝状态</dt><dd><strong>{{ $quoteSignature?->statusLabel() ?? '未推送' }}</strong></dd></div>
<div style="grid-column:span 2"><dt>签署方</dt><dd>{{ $show($onboarding->company_full_name) }}<br>{{ $show($onboarding->esign_operator_name) }} · {{ $show($onboarding->esign_account) }}</dd></div>
</dl>
@if ($quoteSignature?->last_error)
<div class="cod__alert is-error" style="margin:0"><span class="material-icons-outlined" aria-hidden="true">error_outline</span><span>{{ $quoteSignature->last_error }}</span></div>
@endif
@unless ($esignReady)
<p class="cod__help" style="margin:0">E 签宝尚未配置(本地预览环境正常现象),报价确认单无法推送;线下签署后填写说明即可开通。</p>
@endunless
<div class="cod__row">
@if ($canPush)
<form method="POST" action="{{ route('business.courier-onboardings.push-quote', $onboarding) }}">@csrf<button type="submit" class="cod__button cod__button--primary"><span class="material-icons-outlined" aria-hidden="true">send</span>{{ $quoteSignature ? '重新推送' : '推送到 e签宝' }}</button></form>
@endif
@if ($quoteSignature?->esign_sign_flow_id && ! $quoteSigned)
<form method="POST" action="{{ route('business.courier-onboardings.sync-quote', $onboarding) }}">@csrf<button type="submit" class="cod__button"><span class="material-icons-outlined" aria-hidden="true">sync</span>同步签署状态</button></form>
<form method="POST" action="{{ route('business.courier-onboardings.sign-url', $onboarding) }}">@csrf<button type="submit" class="cod__button"><span class="material-icons-outlined" aria-hidden="true">link</span>获取签署链接</button></form>
@endif
@if ($quoteSigned && $quoteSignature->signed_pdf_path)
<a class="cod__button" href="{{ route('business.courier-quote-signatures.download', [$quoteSignature, 'signed']) }}"><span class="material-icons-outlined" aria-hidden="true">task</span>回签单 PDF</a>
<a class="cod__button" href="{{ route('business.courier-quote-signatures.sheet', $onboarding->quoteVersion) }}"><span class="material-icons-outlined" aria-hidden="true">table_view</span>导出电子档</a>
@endif
@if ($quoteSignature?->source_pdf_path)
<a class="cod__button" href="{{ route('business.courier-quote-signatures.download', [$quoteSignature, 'source']) }}"><span class="material-icons-outlined" aria-hidden="true">picture_as_pdf</span>报价确认单 PDF</a>
@endif
</div>
@if (session('quote_sign_url'))
<div class="cod__stack" style="gap:8px;padding:12px;border:1px dashed var(--cod-line, #d9cfb8);border-radius:10px">
<strong style="font-size:13px">签署链接(签署人 {{ $show($onboarding->esign_operator_name) }} 用手机扫码或打开)</strong>
<div style="width:150px;height:150px">{!! \App\Support\QrCode::svg(session('quote_sign_url'), 4, 2) !!}</div>
<input type="text" readonly value="{{ session('quote_sign_url') }}" onclick="this.select()" style="width:100%;font-size:13px;padding:6px 8px;border:1px solid #ddd;border-radius:6px">
<p class="cod__help" style="margin:0">可以直接把链接或二维码发给快递。打开后需先用 {{ $show($onboarding->esign_account) }} 登录 / 实名{{ $onboarding->isPerson() ? '' : ',并以「' . $onboarding->company_full_name . '」企业身份签署' }}。</p>
</div>
@endif
@if ($quoteSignature?->esign_sign_flow_id && ! $quoteSigned && ! $onboarding->isPerson())
<p class="cod__help" style="margin:0">企业签署的任务在 e签宝里归属「{{ $show($onboarding->company_full_name) }}」这家企业:签署人会收到短信;在 e签宝 App 里要切换到这家企业才能看到待签任务。企业名称必须和营业执照完全一致、且已在 e签宝完成企业认证(或由签署人当场认证),否则无法签署。</p>
@endif
<div class="cod__divider"></div>
@if ($isAdmin)
<form method="POST" action="{{ route('business.courier-onboardings.activate', $onboarding) }}" class="cod__stack">
@csrf
@unless ($quoteSigned || $signedAgreement)
<div class="cod__field"><label for="cod-offline">线下签署说明</label><textarea id="cod-offline" name="offline_note" maxlength="1000" placeholder="报价确认单未在 e签宝签完时必填,如:已线下盖章,原件在财务处">{{ old('offline_note') }}</textarea></div>
@endunless
<button type="submit" class="cod__button cod__button--primary"><span class="material-icons-outlined" aria-hidden="true">how_to_reg</span>确认开通</button>
@if ($quoteSigned)<span class="cod__help">报价确认单已签署归档,可以直接开通。</span>@endif
</form>
@else
<p class="cod__help" style="margin:0">推送和开通需要管理员账号。</p>
@endif
</div>
</section>
@elseif ($status === 'activated')
<section class="cod__panel"><div class="cod__panel-body cod__stack">
<div class="cod__alert is-success" style="margin:0"><span class="material-icons-outlined" aria-hidden="true">how_to_reg</span><span>{{ $onboarding->activated_at?->format('Y-m-d H:i') }} 已开通,可在快递资料「入驻快递」查看。</span></div>
<a class="cod__button" href="{{ route('business.pages.show', ['section' => 'courier-payables', 'page' => 'courier-information', 'courier_tab' => 'onboarded']) }}"><span class="material-icons-outlined" aria-hidden="true">open_in_new</span>快递资料 · 入驻快递</a>
<a class="cod__button" href="{{ $quoteUrl }}"><span class="material-icons-outlined" aria-hidden="true">price_change</span>报价管理 · 快递报价(变价)</a>
@if ($quoteSignature?->status === 'archived' && $quoteSignature->signed_pdf_path)
<div class="cod__row">
<a class="cod__button" href="{{ route('business.courier-quote-signatures.download', [$quoteSignature, 'signed']) }}"><span class="material-icons-outlined" aria-hidden="true">task</span>回签单 PDF</a>
<a class="cod__button" href="{{ route('business.courier-quote-signatures.sheet', $onboarding->quoteVersion) }}"><span class="material-icons-outlined" aria-hidden="true">table_view</span>导出电子档</a>
</div>
@endif
</div></section>
@endif
<section class="cod__panel" aria-labelledby="cod-internal">
<div class="cod__panel-head"><h2 class="cod__panel-title" id="cod-internal"><span class="material-icons-outlined" aria-hidden="true">badge</span>内部信息</h2></div>
<div class="cod__panel-body">
@if (in_array($status, ['activated', 'rejected', 'cancelled'], true) || $onboarding->quote_version_id)
<dl class="cod__meta" style="grid-template-columns:1fr 1fr">
<div><dt>系统快递名称</dt><dd>{{ $show($onboarding->courier_name) }}</dd></div>
<div><dt>对账人</dt><dd>{{ $show($onboarding->reconciler) }}</dd></div>
</dl>
@else
<form method="POST" action="{{ route('business.courier-onboardings.internal', $onboarding) }}" class="cod__stack">
@csrf
<div class="cod__field"><label for="cod-internal-name">系统快递名称</label><input id="cod-internal-name" name="courier_name" type="text" maxlength="100" value="{{ $onboarding->courier_name }}" placeholder="如:新北中通"></div>
<div class="cod__field"><label for="cod-internal-reconciler">对账人</label><input id="cod-internal-reconciler" name="reconciler" type="text" maxlength="100" value="{{ $onboarding->reconciler }}"></div>
<button type="submit" class="cod__button">保存</button>
</form>
@endif
</div>
</section>
<section class="cod__panel" aria-labelledby="cod-profile">
<div class="cod__panel-head"><h2 class="cod__panel-title" id="cod-profile"><span class="material-icons-outlined" aria-hidden="true">local_shipping</span>快递资料(我方填写)</h2></div>
<div class="cod__panel-body">
<form method="POST" action="{{ route('business.courier-onboardings.internal', $onboarding) }}" class="cod__stack">
@csrf
<p class="cod__help" style="margin:0">快递方看不到。保存后对齐到快递资料(扣款方式、网点代码等),代码 {{ $onboarding->workplatform_expcode ?: '未填' }}。</p>
@foreach (\App\Models\Business\CourierOnboarding::PROFILE_FIELDS as $field => [$label, $options])
<div class="cod__field">
<label for="cod-profile-{{ $field }}">{{ $label }} *</label>
@if ($options !== null)
<select id="cod-profile-{{ $field }}" name="{{ $field }}" required>
<option value=""></option>
@foreach ($options as $option)
<option value="{{ $option }}" @selected(old($field, $onboarding->{$field}) === $option)>{{ $option }}</option>
@endforeach
</select>
@else
<input id="cod-profile-{{ $field }}" name="{{ $field }}" required type="{{ $field === 'courier_email' ? 'email' : 'text' }}" maxlength="{{ $field === 'network_code' ? 64 : 191 }}" value="{{ old($field, $onboarding->{$field}) }}">
@endif
@error($field)<span class="cod__help" style="color:#b80000">{{ $message }}</span>@enderror
</div>
@endforeach
<button type="submit" class="cod__button">保存快递资料</button>
</form>
</div>
</section>
@if ($status === 'activated')
<section class="cod__panel" aria-labelledby="cod-erp">
<div class="cod__panel-head"><h2 class="cod__panel-title" id="cod-erp"><span class="material-icons-outlined" aria-hidden="true">hub</span>ERP 开通</h2>
@if ($onboarding->erpPending())<span class="cod__pill" style="margin-left:auto;padding:2px 8px;border-radius:6px;font-size:12px;background:#FFF6E5;color:#935F07">待 ERP 开通</span>@else<span class="cod__pill" style="margin-left:auto;padding:2px 8px;border-radius:6px;font-size:12px;background:#EEF6EA;color:#2F6B2A">已开通</span>@endif
</div>
<div class="cod__panel-body cod__stack">
@if ($onboarding->erpPending())
<p class="cod__help" style="margin:0">下一步:ERP 专员开通发货系统账号后,在下方「手动补录」里填 ERP账户ID 保存即可(快递公司代码沿用生成二维码时填的)。快递类型、扣款方式等在上方「快递资料(我方填写)」维护,直接对齐到快递资料。</p>
@else
<dl class="cod__meta" style="grid-template-columns:1fr 1fr">
<div><dt>快递代码</dt><dd>{{ $onboarding->workplatform_expcode }}</dd></div>
<div><dt>ERP账户ID</dt><dd>{{ $onboarding->erp_account_id ?: '—' }}</dd></div>
<div><dt>开通时间</dt><dd>{{ $onboarding->erp_opened_at?->format('Y-m-d H:i') ?? '—' }}</dd></div>
<div><dt>来源</dt><dd>{{ $onboarding->erpSourceLabel() ?: '—' }}</dd></div>
</dl>
@endif
<details>
<summary class="cod__help" style="cursor:pointer">手动补录 ERP 开通信息</summary>
<form method="POST" action="{{ route('business.courier-onboardings.erp-opening', $onboarding) }}" class="cod__stack" style="margin-top:10px">
@csrf
<div class="cod__field"><label for="cod-erp-code">快递代码</label><input id="cod-erp-code" name="workplatform_expcode" type="text" maxlength="64" value="{{ $onboarding->workplatform_expcode }}" placeholder="ERP 开通后的快递代码"></div>
<div class="cod__field"><label for="cod-erp-account">ERP账户ID</label><input id="cod-erp-account" name="erp_account_id" type="text" maxlength="64" value="{{ $onboarding->erp_account_id }}"></div>
<button type="submit" class="cod__button">保存</button>
</form>
</details>
</div>
</section>
@endif
</aside>
</div>
</div>
<script>
document.querySelectorAll('.cod [data-copy-button]').forEach(function (button) {
button.addEventListener('click', function () {
var input = document.querySelector('.cod [data-copy-source]');
if (!input) return;
input.select();
var done = function () { button.lastChild.textContent = '已复制'; setTimeout(function () { button.lastChild.textContent = '复制'; }, 1600); };
if (navigator.clipboard && window.isSecureContext) { navigator.clipboard.writeText(input.value).then(done); } else { document.execCommand('copy'); done(); }
});
});
document.querySelectorAll('.cod form[data-confirm]').forEach(function (form) {
form.addEventListener('submit', function (event) { if (!window.confirm(form.getAttribute('data-confirm'))) event.preventDefault(); });
});
</script>
</x-slot>
</x-layouts.admin>