100 lines
11 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.

<x-layouts.admin>
<x-slot name="title">{{ $entry ? '编辑存量报价' : '录入存量报价' }}</x-slot>
<x-slot name="content">
<style>
.stock-quote { --sq-gold:var(--vip-content-accent-dark,#856632); --sq-border:var(--vip-border,#D8D2C7); --sq-muted:var(--vip-content-muted,#595959); margin:24px 40px; color:var(--vip-content-ink,#171717); font:13px/1.5 "JetBrains Mono","Microsoft YaHei",monospace; }
.stock-quote * { box-sizing:border-box; }
.stock-quote a { color:var(--sq-gold); }
.stock-quote__panel { margin-top:16px; border:1px solid var(--sq-border); border-radius:12px; background:#fff; }
.stock-quote__header { display:flex; align-items:center; gap:8px; margin:0; border-bottom:1px solid var(--sq-border); padding:14px 16px; font-size:14px; font-weight:600; }
.stock-quote__header .material-icons-outlined { color:var(--sq-gold); font-size:19px; }
.stock-quote__body { display:grid; gap:16px; padding:16px; }
.stock-quote__grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:16px; }
.stock-quote__field { display:grid; align-content:start; gap:6px; min-width:0; }
.stock-quote__field label { font-size:12px; font-weight:500; }
.stock-quote__control { width:100%; min-height:34px; border:1px solid var(--sq-border); border-radius:8px; background:#fff; padding:6px 10px; color:inherit; font:inherit; }
.stock-quote__control:focus { border-color:var(--sq-gold); outline:none; box-shadow:0 0 0 3px rgba(133,102,50,.2); }
.stock-quote__hint { margin:0; color:var(--sq-muted); font-size:12px; }
.stock-quote__notice { margin:16px 0 0; border:1px solid var(--sq-border); border-radius:8px; background:var(--vip-content-accent-soft,#F7F0DE); padding:12px 16px; }
.stock-quote__errors { margin-top:16px; border:1px solid var(--vip-danger,#B80000); border-radius:8px; padding:12px 16px; color:var(--vip-danger,#B80000); }
.stock-quote__actions { display:flex; justify-content:flex-end; align-items:center; gap:12px; margin-top:16px; }
.stock-quote__button { display:inline-flex; align-items:center; justify-content:center; gap:6px; min-height:34px; border:1px solid var(--sq-gold); border-radius:8px; background:var(--sq-gold); padding:0 14px; color:#fff; font:inherit; cursor:pointer; }
.stock-quote__button:disabled { cursor:wait; opacity:.7; }
@media(max-width:800px) { .stock-quote { margin:16px; } .stock-quote__grid { grid-template-columns:1fr; } .stock-quote__actions { flex-wrap:wrap; } }
</style>
<main class="stock-quote">
<a href="{{ route('business.pages.show', ['section' => 'courier-payables', 'page' => 'quote-management']) }}">返回报价管理</a>
<p class="stock-quote__notice">选择或手填与发货数据一致的快递名称,保存原报价并核对后提交审核,无需先补快递资料和编号。后续调价沿用报价版本、审核和签署流程。</p>
@if($errors->any())
<div class="stock-quote__errors" role="alert">
@foreach($errors->all() as $error)<div>{{ $error }}</div>@endforeach
<p class="stock-quote__hint">提交失败时请重新选择附件,其他已填内容会保留。</p>
</div>
@endif
<form method="POST" enctype="multipart/form-data" action="{{ $entry ? route('business.courier-stock-quotes.update', $entry) : route('business.courier-stock-quotes.store') }}" data-stock-quote-form>
@csrf
@if($entry) @method('PATCH') @endif
<section class="stock-quote__panel">
<h2 class="stock-quote__header"><span class="material-icons-outlined" aria-hidden="true">local_shipping</span>第一步:确认快递名称</h2>
<div class="stock-quote__body">
@include('business.pages.courier-payables.partials.stock-quote-courier-names')
<div class="stock-quote__field">
<label for="courier_name">快递名称(与发货数据一致)</label>
<input class="stock-quote__control" id="courier_name" name="courier_name" list="stock-courier-names" data-courier-name-input value="{{ old('courier_name', $entry?->courier_name ?? request('courier_name')) }}" maxlength="255" required placeholder="选择或手填完整快递名称">
<p class="stock-quote__hint">输入两字以上可搜索近期发货名称;找不到也可手填,不会新增或改写快递资料。请使用完整名称,不要只填品牌。</p>
</div>
@if($entry)
<p>报价类型:{{ $entry->quote_type }} · 原工作表:{{ $entry->sheet_name }}</p>
<p class="stock-quote__hint">草稿阶段可以更正名称,正式版本生效后通过后续变价管理,不覆盖历史版本。</p>
@else
<div class="stock-quote__grid">
<div class="stock-quote__field">
<label for="quote_type">报价类型</label>
<input class="stock-quote__control" id="quote_type" name="quote_type" list="stock-quote-types" value="{{ old('quote_type', request('quote_type')) }}" maxlength="64" required placeholder="例如:标准快递报价、超长件报价">
<datalist id="stock-quote-types"><option value="标准快递报价"><option value="超长件报价"><option value="大件快递报价"></datalist>
<p class="stock-quote__hint">同一家快递、同一类型只录入一次;后续调整请从对应报价发起变价。</p>
</div>
</div>
@endif
</div>
</section>
<section class="stock-quote__panel">
<h2 class="stock-quote__header"><span class="material-icons-outlined" aria-hidden="true">upload_file</span>第二步:保存原报价与依据</h2>
<div class="stock-quote__body">
@if($entry)
<p class="stock-quote__hint">已保存原报价及附件。草稿阶段可重新上传报价或补充附件,历次原文件均会保留。</p>
<div>@foreach($entry->files as $index => $file)<div><a href="{{ route('business.courier-stock-quotes.download', [$entry, $index]) }}">{{ $file['name'] }}</a></div>@endforeach</div>
@endif
<div class="stock-quote__grid">
<div class="stock-quote__field"><label for="source_quote">{{ $entry ? '替换当前报价 Excel(可选)' : '原报价 Excel(必填)' }}</label><input class="stock-quote__control" id="source_quote" name="source_quote" type="file" accept=".xlsx,.xls" @required(!$entry)><p class="stock-quote__hint">支持 xlsx、xls,单文件不超过 20 MB。原始内容和公式会保留。</p></div>
<div class="stock-quote__field"><label for="sheet_name">工作表名称</label><input class="stock-quote__control" id="sheet_name" name="sheet_name" value="{{ old('sheet_name', $entry?->sheet_name) }}" maxlength="255" placeholder="文件只有一张工作表时可留空"><p class="stock-quote__hint">多工作表文件请填写本次报价所在的准确工作表名称。</p></div>
<div class="stock-quote__field"><label for="confirmation_files">报价确认单、合同及其他依据(可选)</label><input class="stock-quote__control" id="confirmation_files" name="confirmation_files[]" type="file" multiple accept=".pdf,.doc,.docx,.jpg,.jpeg,.png,.xlsx,.xls,.eml,.msg"><p class="stock-quote__hint">最多 10 个,每个不超过 20 MB。</p></div>
<div class="stock-quote__field"><label for="signed_files">历史签署资料(可选)</label><input class="stock-quote__control" id="signed_files" name="signed_files[]" type="file" multiple accept=".pdf,.doc,.docx,.jpg,.jpeg,.png"><p class="stock-quote__hint">上传资料后由审核人核验归档;存量报价审核后按执行日期生效,无需签章。</p></div>
</div>
</div>
</section>
<section class="stock-quote__panel">
<h2 class="stock-quote__header"><span class="material-icons-outlined" aria-hidden="true">fact_check</span>第三步:核对计费规则与执行日期</h2>
<div class="stock-quote__body">
<div class="stock-quote__field"><label for="effective_date">实际开始执行日期</label><input class="stock-quote__control" id="effective_date" name="effective_date" type="date" value="{{ old('effective_date', $entry?->change?->effective_date?->toDateString()) }}" required><p class="stock-quote__hint">请按原报价填写真实执行日期,历史报价不以录入日期代替。</p></div>
<div class="stock-quote__field"><label for="end_date">执行截止日期(可留空)</label><input class="stock-quote__control" id="end_date" name="end_date" type="date" value="{{ old('end_date', $entry?->change?->end_date?->toDateString()) }}"><p class="stock-quote__hint">留空表示长期执行;同一快递、同类报价的执行期间不得重叠,截止日期当天仍适用。</p></div>
<div class="stock-quote__field"><label for="billing_rules">计费规则</label><textarea class="stock-quote__control" id="billing_rules" name="billing_rules" rows="4" minlength="2" maxlength="4000" required placeholder="请核对并记录重量段、首续重、计泡、面单、区域及附加费等原报价规则">{{ old('billing_rules', data_get($entry?->change?->quote_payload, 'billing_rules')) }}</textarea><p class="stock-quote__hint">本次将报价接入版本管理;运费自动核算仍以已实现且经核验的计算规则为准。</p></div>
<div class="stock-quote__field"><label for="summary">录入依据与说明</label><textarea class="stock-quote__control" id="summary" name="summary" rows="3" minlength="2" maxlength="2000" required placeholder="例如:补录历史合作报价,价格以原确认单为准">{{ old('summary', $entry?->change?->summary) }}</textarea></div>
</div>
</section>
<div class="stock-quote__actions"><span class="stock-quote__hint">下一步预览报价逐项核对,再提交审核。</span><button class="stock-quote__button" type="submit"><span class="material-icons-outlined" aria-hidden="true">preview</span>{{ $entry ? '保存修改并预览' : '保存草稿并预览' }}</button></div>
</form>
</main>
<script>
(() => {
const form = document.querySelector('[data-stock-quote-form]');
form?.addEventListener('submit', () => {
const button = form.querySelector('button[type="submit"]');
button.disabled = true;
button.textContent = '正在保存…';
});
})();
</script>
</x-slot>
</x-layouts.admin>