合并:新增素板、快递及商品价格页面
This commit is contained in:
parent
fa9444bbbe
commit
2c0aaab550
@ -183,8 +183,8 @@ return [
|
||||
'title' => '原材料-素板应付',
|
||||
'icon' => 'view_module',
|
||||
'pages' => [
|
||||
['slug' => 'board-prices', 'title' => '素版价格'],
|
||||
['slug' => 'board-reconciliation', 'title' => '素版对账'],
|
||||
['slug' => 'board-prices', 'title' => '素板价格'],
|
||||
['slug' => 'board-reconciliation', 'title' => '素板对账'],
|
||||
['slug' => 'compensation-details', 'title' => '赔付明细'],
|
||||
['slug' => 'board-payables-report', 'title' => '素板应付表'],
|
||||
],
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
@include('business.pages.courier-payables.partials.data-table', [
|
||||
'title' => $page['title'] ?? '借支明细',
|
||||
'filters' => [
|
||||
['name' => 'carrier', 'label' => '快递名称', 'placeholder' => '输入快递名称'],
|
||||
['name' => 'agreement_name', 'label' => '协议签订名称', 'placeholder' => '输入协议名称'],
|
||||
['name' => 'payment_status', 'label' => '是否打款', 'type' => 'select', 'options' => ['' => '全部']],
|
||||
['name' => 'advance_from', 'label' => '借支日期从', 'type' => 'date'],
|
||||
['name' => 'advance_to', 'label' => '借支日期至', 'type' => 'date'],
|
||||
],
|
||||
'columns' => [
|
||||
['key' => 'carrier', 'label' => '快递名称'],
|
||||
['key' => 'agreement_name', 'label' => '协议签订名称'],
|
||||
['key' => 'agreement_amount', 'label' => '借支金额-借款协议'],
|
||||
['key' => 'actual_paid_amount', 'label' => '实际打款金额'],
|
||||
['key' => 'monthly_deduction', 'label' => '本月扣款金额'],
|
||||
['key' => 'deduction_start_month', 'label' => '分期起始扣款月份'],
|
||||
['key' => 'deduction_end_month', 'label' => '分期最后次扣款月份'],
|
||||
['key' => 'remaining_periods', 'label' => '分期剩余期数'],
|
||||
['key' => 'advanced_at', 'label' => '借支日期'],
|
||||
['key' => 'loan_term', 'label' => '借款期限'],
|
||||
['key' => 'remark', 'label' => '备注'],
|
||||
['key' => 'payment_status', 'label' => '是否打款'],
|
||||
['key' => 'payment_month', 'label' => '打款月份'],
|
||||
['key' => 'serial_no', 'label' => '流水号'],
|
||||
['key' => 'agreement_file', 'label' => '借支协议'],
|
||||
['key' => 'reviewer', 'label' => '审核人'],
|
||||
],
|
||||
'emptyText' => '暂无借支明细',
|
||||
])
|
||||
@ -0,0 +1,63 @@
|
||||
@include('business.pages.courier-payables.partials.data-table', [
|
||||
'title' => $page['title'] ?? '记账明细',
|
||||
'filters' => [
|
||||
['name' => 'keyword', 'label' => '工单/订单号', 'placeholder' => '输入编号'],
|
||||
['name' => 'bookkeeping_type', 'label' => '记账类型', 'type' => 'select', 'options' => ['' => '全部']],
|
||||
['name' => 'status', 'label' => '处理状态', 'type' => 'select', 'options' => ['' => '全部']],
|
||||
['name' => 'started_from', 'label' => '发起时间从', 'type' => 'date'],
|
||||
['name' => 'started_to', 'label' => '发起时间至', 'type' => 'date'],
|
||||
],
|
||||
'groups' => [
|
||||
['label' => '记账信息', 'span' => 13],
|
||||
['label' => '订单与处理', 'span' => 16],
|
||||
['label' => '商品信息', 'span' => 12],
|
||||
['label' => '工单补充', 'span' => 3],
|
||||
],
|
||||
'columns' => [
|
||||
['key' => 'started_at', 'label' => '发起时间'],
|
||||
['key' => 'work_order_no', 'label' => '工单编号'],
|
||||
['key' => 'initiator', 'label' => '发起人'],
|
||||
['key' => 'bookkeeping_reason', 'label' => '记账原因'],
|
||||
['key' => 'reason_level_1', 'label' => '记账原因-一级选项'],
|
||||
['key' => 'reason_level_2', 'label' => '记账原因-二级选项'],
|
||||
['key' => 'reason_level_3', 'label' => '记账原因-三级选项'],
|
||||
['key' => 'bookkeeping_type', 'label' => '记账类型'],
|
||||
['key' => 'executor', 'label' => '执行人'],
|
||||
['key' => 'source', 'label' => '记账来源'],
|
||||
['key' => 'amount', 'label' => '记账金额'],
|
||||
['key' => 'remark', 'label' => '记账备注说明'],
|
||||
['key' => 'attachment', 'label' => '上传附件'],
|
||||
['key' => 'attachment_preview', 'label' => '上传附件(预览)'],
|
||||
['key' => 'online_order_no', 'label' => '线上订单号'],
|
||||
['key' => 'internal_order_no', 'label' => '内部单号'],
|
||||
['key' => 'actual_paid_amount', 'label' => '实付金额'],
|
||||
['key' => 'carrier', 'label' => '物流公司'],
|
||||
['key' => 'tracking_no', 'label' => '物流单号'],
|
||||
['key' => 'shop_name', 'label' => '店铺名称'],
|
||||
['key' => 'platform', 'label' => '平台'],
|
||||
['key' => 'shipping_warehouse', 'label' => '订单发货仓库'],
|
||||
['key' => 'processing_status', 'label' => '记账处理状态'],
|
||||
['key' => 'counterparty_agreed', 'label' => '被记账方是否同意记账'],
|
||||
['key' => 'counterparty_note', 'label' => '被记账方处理说明'],
|
||||
['key' => 'specialist_result', 'label' => '专员记账判定结果'],
|
||||
['key' => 'specialist_note', 'label' => '专员处理说明'],
|
||||
['key' => 'updated_at', 'label' => '修改时间'],
|
||||
['key' => 'work_order_type', 'label' => '工单类型'],
|
||||
['key' => 'product_image', 'label' => '商品图片'],
|
||||
['key' => 'product_code', 'label' => '商品编码'],
|
||||
['key' => 'style_code', 'label' => '款式编码'],
|
||||
['key' => 'other_attribute_6', 'label' => '其它属性6'],
|
||||
['key' => 'product_name', 'label' => '商品名称'],
|
||||
['key' => 'platform_sku_id', 'label' => '平台商品skuid'],
|
||||
['key' => 'platform_product_id', 'label' => '平台商品id'],
|
||||
['key' => 'product_quantity', 'label' => '商品数量'],
|
||||
['key' => 'product_price', 'label' => '商品价格'],
|
||||
['key' => 'product_amount', 'label' => '商品金额'],
|
||||
['key' => 'buyer_paid_amount', 'label' => '买家实付'],
|
||||
['key' => 'supplier', 'label' => '供应商'],
|
||||
['key' => 'accepting_department', 'label' => '受理部门'],
|
||||
['key' => 'order_shipped_at', 'label' => '订单发货时间'],
|
||||
['key' => 'work_order_remark', 'label' => '工单备注'],
|
||||
],
|
||||
'emptyText' => '暂无记账明细',
|
||||
])
|
||||
@ -0,0 +1,18 @@
|
||||
@include('business.pages.courier-payables.partials.data-table', [
|
||||
'title' => $page['title'] ?? '赔偿明细',
|
||||
'filters' => [
|
||||
['name' => 'carrier', 'label' => '承运商', 'placeholder' => '输入承运商'],
|
||||
['name' => 'tracking_no', 'label' => '快递单号', 'placeholder' => '输入快递单号'],
|
||||
['name' => 'paid_from', 'label' => '赔付日期从', 'type' => 'date'],
|
||||
['name' => 'paid_to', 'label' => '赔付日期至', 'type' => 'date'],
|
||||
],
|
||||
'columns' => [
|
||||
['key' => 'paid_at', 'label' => '赔付日期'],
|
||||
['key' => 'carrier', 'label' => '承运商'],
|
||||
['key' => 'tracking_no', 'label' => '快递单号'],
|
||||
['key' => 'amount', 'label' => '赔付金额'],
|
||||
['key' => 'reason', 'label' => '赔付原因'],
|
||||
['key' => 'remark', 'label' => '备注'],
|
||||
],
|
||||
'emptyText' => '暂无赔偿明细',
|
||||
])
|
||||
@ -0,0 +1,311 @@
|
||||
<!--
|
||||
快递应付 - 运费对账
|
||||
表头设计来源: 快递应付-运费对账功能页面的表头.xls (45列)
|
||||
-->
|
||||
<style>
|
||||
#main-body > .container {
|
||||
max-width: none;
|
||||
width: auto;
|
||||
margin-left: 1.5rem;
|
||||
margin-right: 1.5rem;
|
||||
}
|
||||
</style>
|
||||
<div class="w-full">
|
||||
<!-- Page Header -->
|
||||
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6">
|
||||
<div>
|
||||
<h1 class="text-xl font-semibold text-gray-800">{{ $page['title'] ?? '运费对账' }}</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter Bar -->
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-4 mb-6">
|
||||
<form method="GET" class="flex flex-wrap items-end gap-3">
|
||||
<div class="flex flex-col min-w-[140px]">
|
||||
<label class="text-xs text-gray-500 mb-1">快递单号</label>
|
||||
<input type="text" name="express_no" value="{{ request('express_no') }}" placeholder="搜索快递单号"
|
||||
class="border border-gray-300 rounded px-3 py-1.5 text-sm focus:ring-1 focus:ring-blue-400 focus:border-blue-400 outline-none">
|
||||
</div>
|
||||
<div class="flex flex-col min-w-[120px]">
|
||||
<label class="text-xs text-gray-500 mb-1">条形码</label>
|
||||
<input type="text" name="barcode" value="{{ request('barcode') }}" placeholder="搜索条形码"
|
||||
class="border border-gray-300 rounded px-3 py-1.5 text-sm focus:ring-1 focus:ring-blue-400 focus:border-blue-400 outline-none">
|
||||
</div>
|
||||
<div class="flex flex-col min-w-[120px]">
|
||||
<label class="text-xs text-gray-500 mb-1">快递名称</label>
|
||||
<input type="text" name="express_name" value="{{ request('express_name') }}" placeholder="快递公司"
|
||||
class="border border-gray-300 rounded px-3 py-1.5 text-sm focus:ring-1 focus:ring-blue-400 focus:border-blue-400 outline-none">
|
||||
</div>
|
||||
<div class="flex flex-col min-w-[120px]">
|
||||
<label class="text-xs text-gray-500 mb-1">平台</label>
|
||||
<select name="platform"
|
||||
class="border border-gray-300 rounded px-3 py-1.5 text-sm focus:ring-1 focus:ring-blue-400 focus:border-blue-400 outline-none bg-white">
|
||||
<option value="">全部</option>
|
||||
<option value="淘宝天猫" {{ request('platform') === '淘宝天猫' ? 'selected' : '' }}>淘宝天猫</option>
|
||||
<option value="京东商城" {{ request('platform') === '京东商城' ? 'selected' : '' }}>京东商城</option>
|
||||
<option value="拼多多" {{ request('platform') === '拼多多' ? 'selected' : '' }}>拼多多</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex flex-col min-w-[110px]">
|
||||
<label class="text-xs text-gray-500 mb-1">供应商</label>
|
||||
<input type="text" name="supplier" value="{{ request('supplier') }}" placeholder="供应商"
|
||||
class="border border-gray-300 rounded px-3 py-1.5 text-sm focus:ring-1 focus:ring-blue-400 focus:border-blue-400 outline-none">
|
||||
</div>
|
||||
<div class="flex flex-col min-w-[130px]">
|
||||
<label class="text-xs text-gray-500 mb-1">发货时间 从</label>
|
||||
<input type="date" name="ship_from" value="{{ request('ship_from') }}"
|
||||
class="border border-gray-300 rounded px-3 py-1.5 text-sm focus:ring-1 focus:ring-blue-400 focus:border-blue-400 outline-none">
|
||||
</div>
|
||||
<div class="flex flex-col min-w-[130px]">
|
||||
<label class="text-xs text-gray-500 mb-1">发货时间 至</label>
|
||||
<input type="date" name="ship_to" value="{{ request('ship_to') }}"
|
||||
class="border border-gray-300 rounded px-3 py-1.5 text-sm focus:ring-1 focus:ring-blue-400 focus:border-blue-400 outline-none">
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<button type="submit"
|
||||
class="bg-blue-500 hover:bg-blue-600 text-white text-sm px-4 py-1.5 rounded transition">
|
||||
查询
|
||||
</button>
|
||||
<a href="{{ url()->current() }}"
|
||||
class="border border-gray-300 text-gray-600 text-sm px-4 py-1.5 rounded hover:bg-gray-50 transition">
|
||||
重置
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Data Table - 45 columns with horizontal scroll -->
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-xs whitespace-nowrap">
|
||||
<thead>
|
||||
<!-- Column Group Headers -->
|
||||
<tr class="bg-gray-100 border-b border-gray-300 text-gray-500 font-medium">
|
||||
<th class="sticky left-0 bg-gray-100 z-10 px-2 py-1.5 text-center border-r border-gray-200" style="min-width:40px">#</th>
|
||||
<!-- 物流信息 (10 cols) -->
|
||||
<th class="px-2 py-1 text-center border-r border-gray-200" colspan="10" style="min-width:800px">物流信息</th>
|
||||
<!-- 订单信息 (8 cols) -->
|
||||
<th class="px-2 py-1 text-center border-r border-gray-200" colspan="8" style="min-width:700px">订单信息</th>
|
||||
<!-- 收件信息 (7 cols) -->
|
||||
<th class="px-2 py-1 text-center border-r border-gray-200" colspan="7" style="min-width:650px">收件信息</th>
|
||||
<!-- 商品规格 (5 cols) -->
|
||||
<th class="px-2 py-1 text-center border-r border-gray-200" colspan="5" style="min-width:380px">商品规格</th>
|
||||
<!-- 平台/店铺 (3 cols) -->
|
||||
<th class="px-2 py-1 text-center border-r border-gray-200" colspan="3" style="min-width:300px">平台/店铺</th>
|
||||
<!-- 供应商/仓库 (5 cols) -->
|
||||
<th class="px-2 py-1 text-center border-r border-gray-200" colspan="5" style="min-width:480px">供应商/仓库</th>
|
||||
<!-- 时间 (3 cols) -->
|
||||
<th class="px-2 py-1 text-center border-r border-gray-200" colspan="3" style="min-width:400px">时间</th>
|
||||
<!-- 备注 (2 cols) -->
|
||||
<th class="px-2 py-1 text-center" colspan="2" style="min-width:220px">备注</th>
|
||||
</tr>
|
||||
<!-- Column Sub-Headers -->
|
||||
<tr class="bg-gray-50 border-b border-gray-200 text-gray-600 font-medium">
|
||||
<th class="sticky left-0 bg-gray-50 z-10 px-2 py-1.5 text-center border-r border-gray-200" style="min-width:40px">#</th>
|
||||
{{-- 物流信息 --}}
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:140px">快递单号</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:100px">快递名称1</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:100px">快递名称2</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200 text-right" style="min-width:70px">运费</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200 text-right" style="min-width:80px">费率</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200 text-right" style="min-width:70px">结算重量</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200 text-right" style="min-width:80px">结算体积</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200 text-right" style="min-width:70px">对账重量</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200 text-right" style="min-width:80px">对账体积</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:120px">换单前单号</th>
|
||||
{{-- 订单信息 --}}
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:140px">交易单号</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:100px">商品ID</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:120px">条形码</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:160px">商品名称</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200 text-right" style="min-width:50px">数量</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200 text-right" style="min-width:70px">金额</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:100px">货号</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:100px">配货单号</th>
|
||||
{{-- 收件信息 --}}
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:50px">省</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:70px">市</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:70px">区</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:200px">收货详细地址</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:70px">收货姓名</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:100px">手机号码</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:90px">座机号码</th>
|
||||
{{-- 商品规格 --}}
|
||||
<th class="px-2 py-1.5 border-r border-gray-200 text-right" style="min-width:60px">长(cm)</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200 text-right" style="min-width:60px">宽(cm)</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200 text-right" style="min-width:60px">高(cm)</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200 text-right" style="min-width:80px">体积(cm³)</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200 text-right" style="min-width:80px">重量(kg)</th>
|
||||
{{-- 平台/店铺 --}}
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:90px">平台</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:130px">店铺名称</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:100px">买家昵称</th>
|
||||
{{-- 供应商/仓库 --}}
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:140px">供应商</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:120px">仓库</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:100px">成品条码</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:120px">成品名称</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:120px">成品供应商</th>
|
||||
{{-- 时间 --}}
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:140px">发货时间</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:120px">下载时间</th>
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:120px">付款时间</th>
|
||||
{{-- 备注 --}}
|
||||
<th class="px-2 py-1.5 border-r border-gray-200" style="min-width:130px">买家留言</th>
|
||||
<th class="px-2 py-1.5" style="min-width:130px">卖家备注</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse ($freightReconciliations ?? [] as $index => $item)
|
||||
<tr class="border-b border-gray-100 hover:bg-blue-50/40 transition">
|
||||
<td class="sticky left-0 bg-white z-10 px-2 py-2 text-center text-gray-400 border-r border-gray-100">
|
||||
{{ ($freightReconciliations->currentPage() - 1) * $freightReconciliations->perPage() + $index + 1 }}
|
||||
</td>
|
||||
{{-- 物流信息 --}}
|
||||
<td class="px-2 py-2 mono text-blue-600 border-r border-gray-100">{{ $item['express_no'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 border-r border-gray-100">{{ $item['express_name1'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 border-r border-gray-100">{{ $item['express_name2'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 text-right font-medium border-r border-gray-100 {{ ($item['freight'] ?? 0) > 0 ? 'text-gray-800' : 'text-gray-300' }}">
|
||||
{{ isset($item['freight']) ? number_format((float) $item['freight'], 2) : '-' }}
|
||||
</td>
|
||||
<td class="px-2 py-2 text-right border-r border-gray-100">{{ $item['rate'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 text-right border-r border-gray-100">{{ isset($item['settle_weight']) ? number_format((float) $item['settle_weight'], 4) : '-' }}</td>
|
||||
<td class="px-2 py-2 text-right border-r border-gray-100">{{ isset($item['settle_volume']) ? number_format((float) $item['settle_volume'], 4) : '-' }}</td>
|
||||
<td class="px-2 py-2 text-right border-r border-gray-100">{{ isset($item['recon_weight']) ? number_format((float) $item['recon_weight'], 4) : '-' }}</td>
|
||||
<td class="px-2 py-2 text-right border-r border-gray-100">{{ isset($item['recon_volume']) ? number_format((float) $item['recon_volume'], 4) : '-' }}</td>
|
||||
<td class="px-2 py-2 text-gray-400 border-r border-gray-100 text-xs">{{ $item['prev_express_no'] ?? '-' }}</td>
|
||||
{{-- 订单信息 --}}
|
||||
<td class="px-2 py-2 mono text-xs text-gray-500 border-r border-gray-100">{{ $item['trade_no'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 mono text-xs text-gray-500 border-r border-gray-100">{{ $item['product_id'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 mono text-gray-700 border-r border-gray-100">{{ $item['barcode'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 border-r border-gray-100 max-w-[160px] truncate" title="{{ $item['product_name'] ?? '' }}">
|
||||
{{ $item['product_name'] ?? '-' }}
|
||||
</td>
|
||||
<td class="px-2 py-2 text-right border-r border-gray-100">{{ $item['qty'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 text-right border-r border-gray-100">{{ isset($item['amount']) ? number_format((float) $item['amount'], 2) : '-' }}</td>
|
||||
<td class="px-2 py-2 text-gray-400 text-xs border-r border-gray-100">{{ $item['item_no'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 text-gray-400 text-xs border-r border-gray-100">{{ $item['pick_no'] ?? '-' }}</td>
|
||||
{{-- 收件信息 --}}
|
||||
<td class="px-2 py-2 border-r border-gray-100">{{ $item['province'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 border-r border-gray-100">{{ $item['city'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 border-r border-gray-100">{{ $item['district'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 text-gray-400 text-xs border-r border-gray-100 max-w-[200px] truncate" title="{{ $item['address'] ?? '' }}">
|
||||
{{ $item['address'] ?? '-' }}
|
||||
</td>
|
||||
<td class="px-2 py-2 border-r border-gray-100">{{ $item['receiver_name'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 mono text-xs border-r border-gray-100">{{ $item['receiver_phone'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 mono text-xs text-gray-400 border-r border-gray-100">{{ $item['receiver_tel'] ?? '-' }}</td>
|
||||
{{-- 商品规格 --}}
|
||||
<td class="px-2 py-2 text-right border-r border-gray-100">{{ isset($item['length']) ? number_format((float) $item['length'], 2) : '-' }}</td>
|
||||
<td class="px-2 py-2 text-right border-r border-gray-100">{{ isset($item['width']) ? number_format((float) $item['width'], 2) : '-' }}</td>
|
||||
<td class="px-2 py-2 text-right border-r border-gray-100">{{ isset($item['height']) ? number_format((float) $item['height'], 2) : '-' }}</td>
|
||||
<td class="px-2 py-2 text-right border-r border-gray-100">{{ isset($item['volume']) ? number_format((float) $item['volume'], 4) : '-' }}</td>
|
||||
<td class="px-2 py-2 text-right border-r border-gray-100">{{ isset($item['weight']) ? number_format((float) $item['weight'], 4) : '-' }}</td>
|
||||
{{-- 平台/店铺 --}}
|
||||
<td class="px-2 py-2 border-r border-gray-100">
|
||||
<span class="platform-tag {{ str_contains($item['platform'] ?? '', '天猫') || str_contains($item['platform'] ?? '', '淘宝') ? 'bg-orange-100 text-orange-700' : (str_contains($item['platform'] ?? '', '京东') ? 'bg-red-100 text-red-700' : (str_contains($item['platform'] ?? '', '拼多多') ? 'bg-pink-100 text-pink-700' : 'bg-gray-100 text-gray-600')) }} text-xs px-1.5 py-0.5 rounded">
|
||||
{{ $item['platform'] ?? '-' }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-2 py-2 text-xs text-gray-500 border-r border-gray-100 max-w-[130px] truncate" title="{{ $item['shop_name'] ?? '' }}">
|
||||
{{ $item['shop_name'] ?? '-' }}
|
||||
</td>
|
||||
<td class="px-2 py-2 text-gray-400 text-xs border-r border-gray-100">{{ $item['buyer_nick'] ?? '-' }}</td>
|
||||
{{-- 供应商/仓库 --}}
|
||||
<td class="px-2 py-2 border-r border-gray-100">{{ $item['supplier'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 text-xs text-gray-500 border-r border-gray-100">{{ $item['warehouse'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 mono text-xs text-gray-400 border-r border-gray-100">{{ $item['finished_barcode'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 text-xs text-gray-400 border-r border-gray-100">{{ $item['finished_name'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 text-xs text-gray-400 border-r border-gray-100">{{ $item['finished_supplier'] ?? '-' }}</td>
|
||||
{{-- 时间 --}}
|
||||
<td class="px-2 py-2 text-xs border-r border-gray-100">{{ $item['ship_time'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 text-xs text-gray-400 border-r border-gray-100">{{ $item['download_time'] ?? '-' }}</td>
|
||||
<td class="px-2 py-2 text-xs text-gray-400 border-r border-gray-100">{{ $item['pay_time'] ?? '-' }}</td>
|
||||
{{-- 备注 --}}
|
||||
<td class="px-2 py-2 text-xs text-gray-400 border-r border-gray-100 max-w-[130px] truncate" title="{{ $item['buyer_msg'] ?? '' }}">
|
||||
{{ $item['buyer_msg'] ?? '-' }}
|
||||
</td>
|
||||
<td class="px-2 py-2 text-xs text-gray-400 max-w-[130px] truncate" title="{{ $item['seller_memo'] ?? '' }}">
|
||||
{{ $item['seller_memo'] ?? '-' }}
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="46" class="text-center py-16 text-gray-400">
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<svg class="w-10 h-10" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"
|
||||
d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"
|
||||
d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
</svg>
|
||||
<span class="text-sm">暂无运费对账数据</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
@if (isset($freightReconciliations) && $freightReconciliations->hasPages())
|
||||
<div class="px-4 py-3 border-t border-gray-200 flex items-center justify-between">
|
||||
<div class="text-sm text-gray-500">
|
||||
共 <span class="font-medium text-gray-700">{{ $freightReconciliations->total() }}</span> 条记录
|
||||
</div>
|
||||
<div class="flex items-center gap-1">
|
||||
@if ($freightReconciliations->onFirstPage())
|
||||
<span class="px-3 py-1 text-sm text-gray-300 border border-gray-200 rounded cursor-not-allowed">上一页</span>
|
||||
@else
|
||||
<a href="{{ $freightReconciliations->previousPageUrl() }}" class="px-3 py-1 text-sm text-gray-600 border border-gray-200 rounded hover:bg-gray-50 transition">上一页</a>
|
||||
@endif
|
||||
|
||||
@php
|
||||
$current = $freightReconciliations->currentPage();
|
||||
$last = $freightReconciliations->lastPage();
|
||||
$start = max(1, $current - 2);
|
||||
$end = min($last, $current + 2);
|
||||
@endphp
|
||||
|
||||
@if ($start > 1)
|
||||
<a href="{{ $freightReconciliations->url(1) }}" class="px-3 py-1 text-sm text-gray-600 border border-gray-200 rounded hover:bg-gray-50 transition">1</a>
|
||||
@if ($start > 2)
|
||||
<span class="px-1 text-gray-400">...</span>
|
||||
@endif
|
||||
@endif
|
||||
|
||||
@for ($p = $start; $p <= $end; $p++)
|
||||
@if ($p === $current)
|
||||
<span class="px-3 py-1 text-sm text-white bg-blue-500 border border-blue-500 rounded">{{ $p }}</span>
|
||||
@else
|
||||
<a href="{{ $freightReconciliations->url($p) }}" class="px-3 py-1 text-sm text-gray-600 border border-gray-200 rounded hover:bg-gray-50 transition">{{ $p }}</a>
|
||||
@endif
|
||||
@endfor
|
||||
|
||||
@if ($end < $last)
|
||||
@if ($end < $last - 1)
|
||||
<span class="px-1 text-gray-400">...</span>
|
||||
@endif
|
||||
<a href="{{ $freightReconciliations->url($last) }}" class="px-3 py-1 text-sm text-gray-600 border border-gray-200 rounded hover:bg-gray-50 transition">{{ $last }}</a>
|
||||
@endif
|
||||
|
||||
@if ($freightReconciliations->hasMorePages())
|
||||
<a href="{{ $freightReconciliations->nextPageUrl() }}" class="px-3 py-1 text-sm text-gray-600 border border-gray-200 rounded hover:bg-gray-50 transition">下一页</a>
|
||||
@else
|
||||
<span class="px-3 py-1 text-sm text-gray-300 border border-gray-200 rounded cursor-not-allowed">下一页</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.mono { font-family: 'SF Mono', 'Fira Code', monospace; font-size: 11px; }
|
||||
.platform-tag { white-space: nowrap; }
|
||||
/* Sticky first column on horizontal scroll */
|
||||
@media (max-width: 768px) {
|
||||
.overflow-x-auto table { font-size: 10px; }
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,19 @@
|
||||
@include('business.pages.courier-payables.partials.data-table', [
|
||||
'title' => $page['title'] ?? '其他扣款补款',
|
||||
'filters' => [
|
||||
['name' => 'project', 'label' => '项目', 'placeholder' => '输入项目名称'],
|
||||
['name' => 'carrier', 'label' => '承运商', 'placeholder' => '输入承运商'],
|
||||
['name' => 'date_from', 'label' => '日期从', 'type' => 'date'],
|
||||
['name' => 'date_to', 'label' => '日期至', 'type' => 'date'],
|
||||
],
|
||||
'columns' => [
|
||||
['key' => 'project', 'label' => '项目'],
|
||||
['key' => 'adjusted_at', 'label' => '日期'],
|
||||
['key' => 'carrier', 'label' => '承运商'],
|
||||
['key' => 'amount', 'label' => '补款金额'],
|
||||
['key' => 'reason', 'label' => '补款原因'],
|
||||
['key' => 'remark', 'label' => '备注'],
|
||||
['key' => 'remark_2', 'label' => '备注2'],
|
||||
],
|
||||
'emptyText' => '暂无其他扣款补款明细',
|
||||
])
|
||||
@ -0,0 +1,342 @@
|
||||
@php
|
||||
$records = $records ?? [];
|
||||
$filters = $filters ?? [];
|
||||
$groups = $groups ?? [];
|
||||
$columns = $columns ?? [];
|
||||
$showIndex = $showIndex ?? true;
|
||||
$hasGroups = count($groups) > 0;
|
||||
$recordCount = is_countable($records) ? count($records) : 0;
|
||||
@endphp
|
||||
|
||||
<style>
|
||||
#main-body > .container {
|
||||
width: auto;
|
||||
max-width: none;
|
||||
margin-right: 1.5rem;
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
|
||||
.courier-subpage {
|
||||
--courier-border: #e5e7eb;
|
||||
--courier-muted: #6b7280;
|
||||
--courier-ink: #1f2937;
|
||||
--courier-accent: #2563eb;
|
||||
}
|
||||
|
||||
.courier-subpage .page-heading {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
margin: 1.5rem 0 1.25rem;
|
||||
}
|
||||
|
||||
.courier-subpage .page-heading h1 {
|
||||
margin: 0;
|
||||
color: var(--courier-ink);
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.courier-subpage .page-heading p {
|
||||
margin: 0.35rem 0 0;
|
||||
color: var(--courier-muted);
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
|
||||
.courier-subpage .filter-panel,
|
||||
.courier-subpage .table-panel {
|
||||
border: 1px solid var(--courier-border);
|
||||
border-radius: 0.75rem;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 4px 14px rgba(31, 41, 55, 0.04);
|
||||
}
|
||||
|
||||
.courier-subpage .filter-panel {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-end;
|
||||
gap: 0.75rem 1rem;
|
||||
padding: 1rem 1.125rem;
|
||||
}
|
||||
|
||||
.courier-subpage .filter-field {
|
||||
display: flex;
|
||||
min-width: 9rem;
|
||||
flex-direction: column;
|
||||
gap: 0.3rem;
|
||||
}
|
||||
|
||||
.courier-subpage .filter-field label {
|
||||
color: var(--courier-muted);
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.courier-subpage .filter-field input,
|
||||
.courier-subpage .filter-field select {
|
||||
min-height: 2.25rem;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 0.375rem;
|
||||
background: #ffffff;
|
||||
padding: 0.35rem 0.65rem;
|
||||
color: var(--courier-ink);
|
||||
font-size: 0.8125rem;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.courier-subpage .filter-field input:focus,
|
||||
.courier-subpage .filter-field select:focus {
|
||||
border-color: var(--courier-accent);
|
||||
box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.12);
|
||||
}
|
||||
|
||||
.courier-subpage .filter-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.courier-subpage .filter-actions button,
|
||||
.courier-subpage .filter-actions a {
|
||||
display: inline-flex;
|
||||
min-height: 2.25rem;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
border-radius: 0.375rem;
|
||||
padding: 0.35rem 0.75rem;
|
||||
font-size: 0.8125rem;
|
||||
transition: background-color 150ms ease, border-color 150ms ease;
|
||||
}
|
||||
|
||||
.courier-subpage .filter-actions button {
|
||||
border: 1px solid var(--courier-accent);
|
||||
background: var(--courier-accent);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.courier-subpage .filter-actions button:hover {
|
||||
background: #1d4ed8;
|
||||
}
|
||||
|
||||
.courier-subpage .filter-actions a {
|
||||
border: 1px solid #d1d5db;
|
||||
color: #4b5563;
|
||||
}
|
||||
|
||||
.courier-subpage .filter-actions a:hover {
|
||||
border-color: #9ca3af;
|
||||
background: #f9fafb;
|
||||
}
|
||||
|
||||
.courier-subpage .table-panel {
|
||||
margin-top: 1.25rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.courier-subpage .table-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
border-bottom: 1px solid var(--courier-border);
|
||||
padding: 0.8rem 1rem;
|
||||
}
|
||||
|
||||
.courier-subpage .table-toolbar strong {
|
||||
color: var(--courier-ink);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.courier-subpage .table-toolbar span {
|
||||
color: var(--courier-muted);
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.courier-subpage .table-scroll {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.courier-subpage table {
|
||||
width: max-content;
|
||||
min-width: 100%;
|
||||
border-collapse: collapse;
|
||||
color: var(--courier-ink);
|
||||
font-size: 0.75rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.courier-subpage th,
|
||||
.courier-subpage td {
|
||||
border-right: 1px solid #eef0f3;
|
||||
border-bottom: 1px solid #eef0f3;
|
||||
padding: 0.6rem 0.7rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.courier-subpage th:last-child,
|
||||
.courier-subpage td:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.courier-subpage thead tr:first-child th {
|
||||
border-bottom-color: #d1d5db;
|
||||
background: #f3f4f6;
|
||||
color: #374151;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.courier-subpage thead tr:last-child th,
|
||||
.courier-subpage thead tr:first-child th[rowspan="2"] {
|
||||
background: #f9fafb;
|
||||
color: #4b5563;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.courier-subpage tbody tr:hover {
|
||||
background: #eff6ff;
|
||||
}
|
||||
|
||||
.courier-subpage .index-column {
|
||||
position: sticky;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
min-width: 3.25rem;
|
||||
background: #ffffff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.courier-subpage thead .index-column {
|
||||
background: #f9fafb;
|
||||
}
|
||||
|
||||
.courier-subpage tbody tr:hover .index-column {
|
||||
background: #eff6ff;
|
||||
}
|
||||
|
||||
.courier-subpage .empty-row td {
|
||||
padding: 4rem 1rem;
|
||||
color: #9ca3af;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
#main-body > .container {
|
||||
margin-right: 0.75rem;
|
||||
margin-left: 0.75rem;
|
||||
}
|
||||
|
||||
.courier-subpage .page-heading {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.courier-subpage .filter-field {
|
||||
min-width: min(100%, 13rem);
|
||||
flex: 1 1 13rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="courier-subpage">
|
||||
<div class="page-heading">
|
||||
<div>
|
||||
<h1>{{ $title }}</h1>
|
||||
@if (! empty($subtitle))
|
||||
<p>{{ $subtitle }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="GET" class="filter-panel" aria-label="{{ $title }}筛选">
|
||||
@foreach ($filters as $filter)
|
||||
<div class="filter-field">
|
||||
<label for="courier-filter-{{ $filter['name'] }}">{{ $filter['label'] }}</label>
|
||||
@if (($filter['type'] ?? 'text') === 'select')
|
||||
<select id="courier-filter-{{ $filter['name'] }}" name="{{ $filter['name'] }}">
|
||||
@foreach ($filter['options'] ?? [] as $value => $label)
|
||||
<option value="{{ $value }}" @selected((string) request($filter['name']) === (string) $value)>{{ $label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@else
|
||||
<input
|
||||
id="courier-filter-{{ $filter['name'] }}"
|
||||
type="{{ $filter['type'] ?? 'text' }}"
|
||||
name="{{ $filter['name'] }}"
|
||||
value="{{ request($filter['name']) }}"
|
||||
placeholder="{{ $filter['placeholder'] ?? '' }}"
|
||||
>
|
||||
@endif
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
<div class="filter-actions">
|
||||
<button type="submit">
|
||||
<span class="material-icons-outlined text-base" aria-hidden="true">search</span>
|
||||
<span>查询</span>
|
||||
</button>
|
||||
<a href="{{ url()->current() }}" aria-label="重置筛选" title="重置筛选">
|
||||
<span class="material-icons-outlined text-base" aria-hidden="true">restart_alt</span>
|
||||
<span>重置</span>
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="table-panel">
|
||||
<div class="table-toolbar">
|
||||
<strong>{{ $title }}</strong>
|
||||
<span>共 {{ $recordCount }} 条</span>
|
||||
</div>
|
||||
|
||||
<div class="table-scroll">
|
||||
<table>
|
||||
<thead>
|
||||
@if ($hasGroups)
|
||||
<tr>
|
||||
@if ($showIndex)
|
||||
<th class="index-column" rowspan="2">序号</th>
|
||||
@endif
|
||||
@foreach ($groups as $group)
|
||||
<th colspan="{{ $group['span'] }}">{{ $group['label'] }}</th>
|
||||
@endforeach
|
||||
</tr>
|
||||
<tr>
|
||||
@foreach ($columns as $column)
|
||||
<th>{{ $column['label'] }}</th>
|
||||
@endforeach
|
||||
</tr>
|
||||
@else
|
||||
<tr>
|
||||
@if ($showIndex)
|
||||
<th class="index-column">序号</th>
|
||||
@endif
|
||||
@foreach ($columns as $column)
|
||||
<th>{{ $column['label'] }}</th>
|
||||
@endforeach
|
||||
</tr>
|
||||
@endif
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse ($records as $index => $record)
|
||||
<tr>
|
||||
@if ($showIndex)
|
||||
<td class="index-column">{{ $index + 1 }}</td>
|
||||
@endif
|
||||
@foreach ($columns as $column)
|
||||
@php($value = data_get($record, $column['key']))
|
||||
<td>{{ $value === null || $value === '' ? '-' : $value }}</td>
|
||||
@endforeach
|
||||
</tr>
|
||||
@empty
|
||||
<tr class="empty-row">
|
||||
<td colspan="{{ count($columns) + ($showIndex ? 1 : 0) }}">
|
||||
<span class="material-icons-outlined block mb-2 text-3xl" aria-hidden="true">table_rows</span>
|
||||
{{ $emptyText ?? '暂无数据' }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,28 @@
|
||||
@include('business.pages.courier-payables.partials.data-table', [
|
||||
'title' => $page['title'] ?? '素板应付表',
|
||||
'showIndex' => false,
|
||||
'filters' => [
|
||||
['name' => 'month', 'label' => '月份', 'type' => 'month'],
|
||||
['name' => 'raw_board_factory', 'label' => '素板厂', 'placeholder' => '输入素板厂'],
|
||||
],
|
||||
'columns' => [
|
||||
['key' => 'raw_board_factory', 'label' => '素板厂'],
|
||||
['key' => 'opening_balance', 'label' => '期初余额'],
|
||||
['key' => 'june_payment_amount', 'label' => '6月打款金额'],
|
||||
['key' => 'refund', 'label' => '回款'],
|
||||
['key' => 'zhiyu_temporary_warehouse', 'label' => '志宇临时仓'],
|
||||
['key' => 'haoyuan', 'label' => '浩远'],
|
||||
['key' => 'xinjie', 'label' => '信杰'],
|
||||
['key' => 'jinyu', 'label' => '金舆'],
|
||||
['key' => 'suyang', 'label' => '苏阳'],
|
||||
['key' => 'yongcheng_haohui', 'label' => '永成皓辉'],
|
||||
['key' => 'tongsheng_lamination_factory', 'label' => '桐盛压贴厂'],
|
||||
['key' => 'caoxian_songda', 'label' => '曹县松达'],
|
||||
['key' => 'xusen', 'label' => '旭森'],
|
||||
['key' => 'compensation', 'label' => '赔付'],
|
||||
['key' => 'cuiqiao_temporary_warehouse', 'label' => '崔桥临时仓'],
|
||||
['key' => 'invoice_points', 'label' => '票点'],
|
||||
['key' => 'june_balance_due', 'label' => '6月欠款'],
|
||||
],
|
||||
'emptyText' => '暂无素板应付汇总数据',
|
||||
])
|
||||
@ -0,0 +1,21 @@
|
||||
@include('business.pages.courier-payables.partials.data-table', [
|
||||
'title' => $page['title'] ?? '素板价格',
|
||||
'showIndex' => false,
|
||||
'filters' => [
|
||||
['name' => 'price_type', 'label' => '价格类型', 'type' => 'select', 'options' => ['' => '全部']],
|
||||
['name' => 'material_name', 'label' => '原料名称', 'placeholder' => '输入原料名称'],
|
||||
['name' => 'material_no', 'label' => '原料编号', 'placeholder' => '输入原料编号'],
|
||||
['name' => 'target_vendor', 'label' => '目标厂商', 'placeholder' => '输入目标厂商'],
|
||||
['name' => 'vendor_type', 'label' => '厂商类型', 'type' => 'select', 'options' => ['' => '全部']],
|
||||
],
|
||||
'columns' => [
|
||||
['key' => 'price_type', 'label' => '价格类型'],
|
||||
['key' => 'material_name', 'label' => '原料名称'],
|
||||
['key' => 'material_no', 'label' => '原料编号'],
|
||||
['key' => 'production_no', 'label' => '生产编号'],
|
||||
['key' => 'latest_price', 'label' => '最新价格'],
|
||||
['key' => 'target_vendor', 'label' => '目标厂商'],
|
||||
['key' => 'vendor_type', 'label' => '厂商类型'],
|
||||
],
|
||||
'emptyText' => '暂无素板价格数据',
|
||||
])
|
||||
@ -0,0 +1,36 @@
|
||||
@include('business.pages.courier-payables.partials.data-table', [
|
||||
'title' => $page['title'] ?? '素板对账',
|
||||
'showIndex' => false,
|
||||
'filters' => [
|
||||
['name' => 'production_no', 'label' => '原料生产编号', 'placeholder' => '输入生产编号'],
|
||||
['name' => 'material_name', 'label' => '原料名称', 'placeholder' => '输入原料名称'],
|
||||
['name' => 'outbound_vendor', 'label' => '出库厂商', 'placeholder' => '输入出库厂商'],
|
||||
['name' => 'arrival_vendor', 'label' => '到货厂商', 'placeholder' => '输入到货厂商'],
|
||||
['name' => 'stock_in_from', 'label' => '入库日期从', 'type' => 'date'],
|
||||
['name' => 'stock_in_to', 'label' => '入库日期至', 'type' => 'date'],
|
||||
],
|
||||
'columns' => [
|
||||
['key' => 'stocked_in_at', 'label' => '入库日期'],
|
||||
['key' => 'stocked_out_at', 'label' => '出库日期'],
|
||||
['key' => 'production_no', 'label' => '原料生产编号'],
|
||||
['key' => 'material_name', 'label' => '原料名称'],
|
||||
['key' => 'outbound_quantity', 'label' => '出库数量'],
|
||||
['key' => 'unit', 'label' => '单位'],
|
||||
['key' => 'return_flag', 'label' => '退货标识'],
|
||||
['key' => 'outbound_vendor', 'label' => '出库厂商'],
|
||||
['key' => 'arrival_vendor', 'label' => '到货厂商'],
|
||||
['key' => 'batch_date', 'label' => '批次日期'],
|
||||
['key' => 'outbound_no', 'label' => '出库单号'],
|
||||
['key' => 'outbound_remark', 'label' => '出库备注'],
|
||||
['key' => 'requisition_no', 'label' => '申领单号'],
|
||||
['key' => 'number_type', 'label' => '单号类型'],
|
||||
['key' => 'delivery_no', 'label' => '送货单号'],
|
||||
['key' => 'received_quantity', 'label' => '实收数量'],
|
||||
['key' => 'unit_price', 'label' => '单价'],
|
||||
['key' => 'reconciliation_amount', 'label' => '对账金额'],
|
||||
['key' => 'freight_with_allocation', 'label' => '运费(包含分摊运费)'],
|
||||
['key' => 'allocated_freight', 'label' => '分摊运费'],
|
||||
['key' => 'freight', 'label' => '运费'],
|
||||
],
|
||||
'emptyText' => '暂无素板对账数据',
|
||||
])
|
||||
@ -0,0 +1,18 @@
|
||||
@include('business.pages.courier-payables.partials.data-table', [
|
||||
'title' => $page['title'] ?? '赔付明细',
|
||||
'showIndex' => true,
|
||||
'filters' => [
|
||||
['name' => 'lamination_factory', 'label' => '压贴厂', 'placeholder' => '输入压贴厂'],
|
||||
['name' => 'raw_board_factory', 'label' => '素板厂', 'placeholder' => '输入素板厂'],
|
||||
['name' => 'reason', 'label' => '原因', 'placeholder' => '输入赔付原因'],
|
||||
],
|
||||
'columns' => [
|
||||
['key' => 'lamination_factory', 'label' => '压贴厂'],
|
||||
['key' => 'raw_board_factory', 'label' => '素板厂'],
|
||||
['key' => 'reason', 'label' => '原因'],
|
||||
['key' => 'quantity', 'label' => '数量'],
|
||||
['key' => 'unit_price', 'label' => '单价'],
|
||||
['key' => 'amount', 'label' => '金额'],
|
||||
],
|
||||
'emptyText' => '暂无素板赔付明细',
|
||||
])
|
||||
@ -0,0 +1,447 @@
|
||||
<style>
|
||||
#main-body > .container {
|
||||
max-width: none;
|
||||
width: auto;
|
||||
margin-left: 1.5rem;
|
||||
margin-right: 1.5rem;
|
||||
}
|
||||
.product-prices-filter-bar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-end;
|
||||
gap: 1rem;
|
||||
padding: 1.25rem 1.5rem;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 0.75rem;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 4px 12px rgba(31, 41, 55, 0.04);
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.product-prices-filter-bar .filter-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
.product-prices-filter-bar .filter-label {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
color: #6b7280;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.025em;
|
||||
}
|
||||
|
||||
.product-prices-filter-bar input,
|
||||
.product-prices-filter-bar select {
|
||||
height: 2.5rem;
|
||||
padding: 0 0.75rem;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
color: #1f2937;
|
||||
background: #f9fafb;
|
||||
transition: border-color 150ms, box-shadow 150ms;
|
||||
min-width: 10rem;
|
||||
}
|
||||
|
||||
.product-prices-filter-bar input:focus,
|
||||
.product-prices-filter-bar select:focus {
|
||||
outline: none;
|
||||
border-color: #4f46e5;
|
||||
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.btn-filter {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
height: 2.5rem;
|
||||
padding: 0 1.25rem;
|
||||
border-radius: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: background 150ms;
|
||||
}
|
||||
|
||||
.btn-filter-primary {
|
||||
background: #4f46e5;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.btn-filter-primary:hover {
|
||||
background: #4338ca;
|
||||
}
|
||||
|
||||
.btn-filter-secondary {
|
||||
background: #f3f4f6;
|
||||
color: #374151;
|
||||
}
|
||||
|
||||
.btn-filter-secondary:hover {
|
||||
background: #e5e7eb;
|
||||
}
|
||||
|
||||
.price-tag {
|
||||
display: inline-block;
|
||||
padding: 0.15rem 0.65rem;
|
||||
border-radius: 999px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.price-tag.dingjia {
|
||||
background: #e0e7ff;
|
||||
color: #3730a3;
|
||||
}
|
||||
|
||||
.price-tag.bianjia {
|
||||
background: #fef3c7;
|
||||
color: #92400e;
|
||||
}
|
||||
|
||||
.price-diff-positive {
|
||||
color: #16a34a;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.price-diff-negative {
|
||||
color: #dc2626;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.price-diff-zero {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.data-table-wrapper {
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 0.75rem;
|
||||
background: #ffffff;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 12px rgba(31, 41, 55, 0.04);
|
||||
}
|
||||
|
||||
.data-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.data-table thead {
|
||||
background: #f9fafb;
|
||||
border-bottom: 2px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.data-table thead th {
|
||||
padding: 0.85rem 1rem;
|
||||
text-align: left;
|
||||
font-weight: 700;
|
||||
color: #374151;
|
||||
font-size: 0.8rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.025em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.data-table thead th.right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.data-table tbody tr {
|
||||
border-bottom: 1px solid #f3f4f6;
|
||||
transition: background 120ms;
|
||||
}
|
||||
|
||||
.data-table tbody tr:hover {
|
||||
background: #f9fafb;
|
||||
}
|
||||
|
||||
.data-table tbody td {
|
||||
padding: 0.75rem 1rem;
|
||||
color: #4b5563;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.data-table tbody td.right {
|
||||
text-align: right;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.data-table tbody td.mono {
|
||||
font-family: 'SF Mono', 'Cascadia Code', 'Consolas', monospace;
|
||||
font-size: 0.8rem;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.summary-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0.85rem 1.5rem;
|
||||
background: #f9fafb;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
font-size: 0.85rem;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.summary-bar strong {
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.pagination-wrapper {
|
||||
padding: 1rem 1.5rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.pagination-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
padding: 0 0.6rem;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 0.4rem;
|
||||
font-size: 0.85rem;
|
||||
color: #374151;
|
||||
background: #ffffff;
|
||||
cursor: pointer;
|
||||
transition: all 120ms;
|
||||
}
|
||||
|
||||
.pagination-btn:hover {
|
||||
border-color: #4f46e5;
|
||||
color: #4f46e5;
|
||||
}
|
||||
|
||||
.pagination-btn.active {
|
||||
background: #4f46e5;
|
||||
border-color: #4f46e5;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="my-6">
|
||||
{{-- Page header --}}
|
||||
<div class="flex items-center justify-between mb-5">
|
||||
<div>
|
||||
<h1 class="text-xl font-bold text-gray-900">
|
||||
{{ $page['title'] ?? '商品价格' }}
|
||||
</h1>
|
||||
<p class="text-sm text-gray-500 mt-1">
|
||||
管理供应商商品的定价与变价记录
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<button class="btn-filter btn-filter-secondary">
|
||||
<span class="material-icons-outlined text-base">file_download</span>
|
||||
导出
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Filter bar --}}
|
||||
<form method="GET" class="product-prices-filter-bar">
|
||||
<div class="filter-group">
|
||||
<label class="filter-label">条形码</label>
|
||||
<input type="text" name="barcode" placeholder="输入条形码搜索..."
|
||||
value="{{ request('barcode') }}">
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label class="filter-label">价格类型</label>
|
||||
<select name="price_type">
|
||||
<option value="">全部</option>
|
||||
<option value="0" {{ request('price_type') === '0' ? 'selected' : '' }}>定价</option>
|
||||
<option value="1" {{ request('price_type') === '1' ? 'selected' : '' }}>变价</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label class="filter-label">是否采购降本</label>
|
||||
<select name="cost_reduction">
|
||||
<option value="">全部</option>
|
||||
<option value="1" {{ request('cost_reduction') === '1' ? 'selected' : '' }}>是</option>
|
||||
<option value="0" {{ request('cost_reduction') === '0' ? 'selected' : '' }}>否</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label class="filter-label">生效日期起</label>
|
||||
<input type="date" name="effective_from" value="{{ request('effective_from') }}">
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label class="filter-label">生效日期止</label>
|
||||
<input type="date" name="effective_to" value="{{ request('effective_to') }}">
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label class="filter-label"> </label>
|
||||
<div class="flex gap-2">
|
||||
<button type="submit" class="btn-filter btn-filter-primary">
|
||||
<span class="material-icons-outlined text-base">search</span>
|
||||
查询
|
||||
</button>
|
||||
<a href="{{ route('business.pages.show', ['company_id' => company_id(), 'section' => $section['slug'], 'page' => $page['slug']]) }}"
|
||||
class="btn-filter btn-filter-secondary">
|
||||
<span class="material-icons-outlined text-base">refresh</span>
|
||||
重置
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{{-- Data table --}}
|
||||
<div class="data-table-wrapper">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>条形码</th>
|
||||
<th>价格类型</th>
|
||||
<th>变价类型</th>
|
||||
<th>是否采购降本</th>
|
||||
<th class="right">变价前价格</th>
|
||||
<th class="right">变价后价格</th>
|
||||
<th class="right">差价</th>
|
||||
<th>申请人</th>
|
||||
<th>备注</th>
|
||||
<th>生效开始时间</th>
|
||||
<th>生效结束时间</th>
|
||||
<th>流程完成时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse ($productPrices ?? [] as $index => $item)
|
||||
@php
|
||||
$priceTypeLabel = ($item->price_type ?? '') === '1' ? '变价' : '定价';
|
||||
@endphp
|
||||
<tr>
|
||||
<td class="mono">{{ ($productPrices->currentPage() - 1) * $productPrices->perPage() + $index + 1 }}</td>
|
||||
<td class="mono">{{ $item->barcode ?? '-' }}</td>
|
||||
<td>
|
||||
<span class="price-tag {{ $priceTypeLabel === '变价' ? 'bianjia' : 'dingjia' }}">
|
||||
{{ $priceTypeLabel }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ $item->change_type ?? '-' }}</td>
|
||||
<td>
|
||||
@if (($item->cost_reduction ?? '') === '1')
|
||||
<span class="material-icons-outlined text-green-600 text-lg">check_circle</span>
|
||||
@elseif (($item->cost_reduction ?? '') === '0')
|
||||
<span class="material-icons-outlined text-red-400 text-lg">cancel</span>
|
||||
@else
|
||||
<span class="text-gray-300">-</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="right">{{ isset($item->price_before) && $item->price_before !== null ? number_format((float) $item->price_before, 2) : '-' }}</td>
|
||||
<td class="right">{{ isset($item->price_after) && $item->price_after !== null ? number_format((float) $item->price_after, 2) : '-' }}</td>
|
||||
<td class="right">
|
||||
@php
|
||||
$diff = $item->price_diff ?? null;
|
||||
@endphp
|
||||
@if (isset($diff))
|
||||
<span class="{{ $diff > 0 ? 'price-diff-positive' : ($diff < 0 ? 'price-diff-negative' : 'price-diff-zero') }}">
|
||||
{{ $diff > 0 ? '+' : '' }}{{ number_format((float) $diff, 2) }}
|
||||
</span>
|
||||
@else
|
||||
-
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ $item->applicant ?? '-' }}</td>
|
||||
<td>
|
||||
@if (!empty($item->remark))
|
||||
<span title="{{ $item->remark }}">
|
||||
{{ mb_strlen($item->remark) > 12 ? mb_substr($item->remark, 0, 12) . '...' : $item->remark }}
|
||||
</span>
|
||||
@else
|
||||
-
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ $item->effective_start ?? '-' }}</td>
|
||||
<td>{{ $item->effective_end ?? '-' }}</td>
|
||||
<td>{{ $item->completed_at ?? '-' }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="13" class="text-center py-12 text-gray-400">
|
||||
<span class="material-icons-outlined text-4xl mb-2 block">inventory_2</span>
|
||||
暂无商品价格数据
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{-- Summary bar --}}
|
||||
@if (!empty($productPrices) && method_exists($productPrices, 'total'))
|
||||
<div class="summary-bar">
|
||||
<span>
|
||||
共 <strong>{{ $productPrices->total() }}</strong> 条记录
|
||||
</span>
|
||||
<span>
|
||||
当前第 <strong>{{ $productPrices->currentPage() }}</strong> / <strong>{{ $productPrices->lastPage() }}</strong> 页
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{{-- Pagination --}}
|
||||
@if (isset($productPrices) && $productPrices->hasPages())
|
||||
<div class="pagination-wrapper">
|
||||
<div class="flex items-center gap-1.5">
|
||||
{{-- Previous --}}
|
||||
@if ($productPrices->onFirstPage())
|
||||
<span class="pagination-btn opacity-40 cursor-not-allowed">
|
||||
<span class="material-icons-outlined text-sm">chevron_left</span>
|
||||
</span>
|
||||
@else
|
||||
<a href="{{ $productPrices->previousPageUrl() }}" class="pagination-btn">
|
||||
<span class="material-icons-outlined text-sm">chevron_left</span>
|
||||
</a>
|
||||
@endif
|
||||
|
||||
{{-- Page numbers --}}
|
||||
@php
|
||||
$current = $productPrices->currentPage();
|
||||
$last = $productPrices->lastPage();
|
||||
$start = max(1, $current - 2);
|
||||
$end = min($last, $current + 2);
|
||||
@endphp
|
||||
|
||||
@if ($start > 1)
|
||||
<a href="{{ $productPrices->url(1) }}" class="pagination-btn">1</a>
|
||||
@if ($start > 2)
|
||||
<span class="pagination-btn opacity-50 cursor-default">...</span>
|
||||
@endif
|
||||
@endif
|
||||
|
||||
@for ($i = $start; $i <= $end; $i++)
|
||||
<a href="{{ $productPrices->url($i) }}" class="pagination-btn {{ $i === $current ? 'active' : '' }}">
|
||||
{{ $i }}
|
||||
</a>
|
||||
@endfor
|
||||
|
||||
@if ($end < $last)
|
||||
@if ($end < $last - 1)
|
||||
<span class="pagination-btn opacity-50 cursor-default">...</span>
|
||||
@endif
|
||||
<a href="{{ $productPrices->url($last) }}" class="pagination-btn">{{ $last }}</a>
|
||||
@endif
|
||||
|
||||
{{-- Next --}}
|
||||
@if ($productPrices->hasMorePages())
|
||||
<a href="{{ $productPrices->nextPageUrl() }}" class="pagination-btn">
|
||||
<span class="material-icons-outlined text-sm">chevron_right</span>
|
||||
</a>
|
||||
@else
|
||||
<span class="pagination-btn opacity-40 cursor-not-allowed">
|
||||
<span class="material-icons-outlined text-sm">chevron_right</span>
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
Loading…
x
Reference in New Issue
Block a user