100 lines
11 KiB
PHP
100 lines
11 KiB
PHP
<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>
|