新增功能页面: - 货款对账 (payment-reconciliation): 入库+代发合并对账,228K+2.8M条记录 - 退货对账 (return-reconciliation): finance_purchaseReturn, 36791行 - 发票扣款 (invoice-deductions): finance_invoiceDeduction, 195行 - 赔偿明细 (compensation-details): 纸板厂+压板厂 UNION, 98行 - 借支明细 (advance-details): finance_advanceLoans, 4行 - 样品扣款 (sample-deductions): finance_sampleDeduction, 12行 后端: - JianSunConnection: PDO_ODBC 直连 SQL Server - SupplierPayableRepository: 5个子页面的数据查询+分页 - GoodsReconciliationRepository: 货款对账数据查询 - 15个新API路由 (supplier-payables/*) - 12个JianSun Eloquent模型 前端: - 6个Blade视图 + 6个Vue组件 - webpack.mix.js 新增5个编译入口 - show.blade.php 动态视图解析
140 lines
9.5 KiB
PHP
140 lines
9.5 KiB
PHP
<div id="goods-reconciliation-app" class="goods-reconciliation-page">
|
|
<div v-cloak>
|
|
{{-- 统计卡片 --}}
|
|
<div class="grid grid-cols-4 gap-4 mb-6">
|
|
<div class="bg-white rounded-xl border border-gray-100 p-5 shadow-sm">
|
|
<div class="text-sm text-gray-500 mb-1">对账总金额</div>
|
|
<div class="text-2xl font-bold text-gray-800">@{{ formatMoney(summary.totalAmount) }}</div>
|
|
</div>
|
|
<div class="bg-white rounded-xl border border-gray-100 p-5 shadow-sm">
|
|
<div class="text-sm text-gray-500 mb-1">预估总金额</div>
|
|
<div class="text-2xl font-bold text-gray-800">@{{ formatMoney(summary.totalGuessAmount) }}</div>
|
|
</div>
|
|
<div class="bg-white rounded-xl border border-gray-100 p-5 shadow-sm">
|
|
<div class="text-sm text-gray-500 mb-1">已发出</div>
|
|
<div class="text-2xl font-bold text-green-600">@{{ summary.sentCount.toLocaleString() }}</div>
|
|
</div>
|
|
<div class="bg-white rounded-xl border border-gray-100 p-5 shadow-sm">
|
|
<div class="text-sm text-gray-500 mb-1">未发出</div>
|
|
<div class="text-2xl font-bold text-orange-500">@{{ summary.unsentCount.toLocaleString() }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- 筛选栏 --}}
|
|
<div class="bg-white rounded-xl border border-gray-100 p-4 mb-4 shadow-sm">
|
|
<div class="flex flex-wrap items-center gap-3 mb-3">
|
|
<el-select v-model="filters.record_type" placeholder="记录类型" size="small" style="width: 140px" @change="onFilterChange">
|
|
<el-option label="全部记录" value="all"></el-option>
|
|
<el-option label="入库对账" value="purchase"></el-option>
|
|
<el-option label="代发对账" value="sale"></el-option>
|
|
</el-select>
|
|
<el-select v-model="filters.supplier" placeholder="供应商" size="small" style="width: 160px" filterable clearable @change="onFilterChange">
|
|
<el-option v-for="s in options.suppliers" :key="s" :label="s" :value="s"></el-option>
|
|
</el-select>
|
|
<el-select v-model="filters.warehouse" placeholder="仓库" size="small" style="width: 140px" filterable clearable @change="onFilterChange">
|
|
<el-option v-for="w in options.warehouses" :key="w" :label="w" :value="w"></el-option>
|
|
</el-select>
|
|
<el-input v-model="filters.stock_no" placeholder="入库单号" size="small" style="width: 140px" clearable @clear="onFilterChange" @keyup.enter="onFilterChange"></el-input>
|
|
<el-input v-model="filters.purchase_no" placeholder="采购单号" size="small" style="width: 140px" clearable @clear="onFilterChange" @keyup.enter="onFilterChange"></el-input>
|
|
</div>
|
|
<div class="flex flex-wrap items-center gap-3">
|
|
<el-input v-model="filters.product_code" placeholder="商品编码" size="small" style="width: 140px" clearable @clear="onFilterChange" @keyup.enter="onFilterChange"></el-input>
|
|
<el-input v-model="filters.express_no" placeholder="快递单号" size="small" style="width: 140px" clearable @clear="onFilterChange" @keyup.enter="onFilterChange"></el-input>
|
|
<el-date-picker v-model="filters.send_time_range" type="daterange"
|
|
start-placeholder="发货开始" end-placeholder="发货结束" size="small"
|
|
style="width: 260px" value-format="yyyy-MM-dd" @change="onFilterChange">
|
|
</el-date-picker>
|
|
<el-date-picker v-model="filters.create_time_range" type="daterange"
|
|
start-placeholder="创建开始" end-placeholder="创建结束" size="small"
|
|
style="width: 260px" value-format="yyyy-MM-dd" @change="onFilterChange">
|
|
</el-date-picker>
|
|
<el-select v-model="filters.sent_status" placeholder="发出状态" size="small" style="width: 120px" clearable @change="onFilterChange">
|
|
<el-option label="全部" value="all"></el-option>
|
|
<el-option label="已发出" value="sent"></el-option>
|
|
<el-option label="未发出" value="unsent"></el-option>
|
|
</el-select>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Tab 切换 --}}
|
|
<div class="flex gap-1 mb-4">
|
|
<button v-for="tab in tabs" :key="tab.key"
|
|
@click="switchTab(tab.key)"
|
|
:class="['px-4 py-2 rounded-lg text-sm font-medium transition-colors',
|
|
activeTab === tab.key ? 'bg-indigo-600 text-white shadow-sm' : 'bg-white text-gray-600 border border-gray-200 hover:bg-gray-50']">
|
|
@{{ tab.label }}
|
|
</button>
|
|
</div>
|
|
|
|
{{-- 数据表格 --}}
|
|
<div class="bg-white rounded-xl border border-gray-100 shadow-sm overflow-hidden">
|
|
<div v-if="loading" class="flex items-center justify-center py-20">
|
|
<span class="text-gray-400">加载中...</span>
|
|
</div>
|
|
<el-table v-else :data="tableData" stripe border style="width: 100%" size="small"
|
|
:default-sort="{prop: 'createTime', order: 'descending'}"
|
|
@sort-change="onSortChange">
|
|
<el-table-column type="index" label="#" width="55" fixed="left"></el-table-column>
|
|
<el-table-column prop="recordType" label="类型" width="80">
|
|
<template slot-scope="scope">
|
|
<el-tag size="mini" :type="scope.row.recordType === 'purchase' ? 'primary' : 'success'">
|
|
@{{ scope.row.recordType === 'purchase' ? '入库' : '代发' }}
|
|
</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="stockNo" label="入库单号" width="120" show-overflow-tooltip></el-table-column>
|
|
<el-table-column prop="purchaseNo" label="采购单号" width="110" show-overflow-tooltip></el-table-column>
|
|
<el-table-column prop="sendTime" label="发货时间" width="145" sortable="custom"></el-table-column>
|
|
<el-table-column prop="supplier" label="供应商" width="110" show-overflow-tooltip></el-table-column>
|
|
<el-table-column prop="skuCode" label="货号" width="130" show-overflow-tooltip></el-table-column>
|
|
<el-table-column prop="productCode" label="商品编码" width="120" show-overflow-tooltip></el-table-column>
|
|
<el-table-column prop="skuName" label="规格名称" width="180" show-overflow-tooltip></el-table-column>
|
|
<el-table-column prop="qty" label="数量" width="80" align="right"></el-table-column>
|
|
<el-table-column label="单价" width="100" align="right">
|
|
<template slot-scope="scope">@{{ formatMoney(scope.row.unitPrice) }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="金额" width="120" align="right">
|
|
<template slot-scope="scope">@{{ formatMoney(scope.row.amount) }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="预估单价" width="100" align="right">
|
|
<template slot-scope="scope">@{{ formatMoney(scope.row.guessUnitPrice) }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="预估金额" width="120" align="right">
|
|
<template slot-scope="scope">@{{ formatMoney(scope.row.guessAmount) }}</template>
|
|
</el-table-column>
|
|
<el-table-column prop="supplierGoodsCode" label="供应商商品编码" width="140" show-overflow-tooltip></el-table-column>
|
|
<el-table-column prop="remark" label="备注" width="150" show-overflow-tooltip></el-table-column>
|
|
<el-table-column prop="warehouse" label="仓库名称" width="100" show-overflow-tooltip></el-table-column>
|
|
<el-table-column prop="createTime" label="创建时间" width="145" sortable="custom"></el-table-column>
|
|
<el-table-column prop="expressName" label="快递名称" width="100" show-overflow-tooltip></el-table-column>
|
|
<el-table-column prop="expressNo" label="快递单号" width="130" show-overflow-tooltip></el-table-column>
|
|
<el-table-column label="未发出" width="90" align="center">
|
|
<template slot-scope="scope">
|
|
<el-tag v-if="scope.row.isUnsent" size="mini" type="warning">未发出</el-tag>
|
|
<span v-else class="text-gray-400">-</span>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
{{-- 分页 --}}
|
|
<div class="flex items-center justify-between px-4 py-3 border-t border-gray-100" v-if="!loading">
|
|
<div class="text-sm text-gray-500">共 @{{ total }} 条记录</div>
|
|
<el-pagination
|
|
background
|
|
layout="prev, pager, next, sizes, jumper"
|
|
:total="total"
|
|
:page-size="pageSize"
|
|
:current-page.sync="currentPage"
|
|
:page-sizes="[25, 50, 100]"
|
|
@size-change="onPageSizeChange"
|
|
@current-change="onPageChange">
|
|
</el-pagination>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@push('body_end')
|
|
<script src="{{ asset('public/js/ecommerce-finance/goods-reconciliations.min.js') }}"></script>
|
|
@endpush
|