合并:同步供应商应付子页面与账单支线

This commit is contained in:
WuYongJie 2026-07-21 19:19:14 +08:00
commit d6702e4e87
16 changed files with 1342 additions and 3 deletions

View File

@ -65,6 +65,11 @@ class Pages extends Controller
abort_if(empty($pageConfig), 404);
// 如果该 page 是一个 children-only 的父级分组,访问它时跳到第一个子页面
if (! empty($pageConfig['children']) && empty($pageConfig['tabs'])) {
return $this->redirectToPage($sectionConfig, $pageConfig['children'][0]);
}
$tabs = collect($pageConfig['tabs'] ?? []);
if ($tabs->isEmpty()) {

View File

@ -44,6 +44,47 @@ class ShowInAdmin
$parameters['tab'] = $page['tabs'][0]['slug'];
}
$children = $page['children'] ?? [];
if (! empty($children)) {
// 父级 page 渲染为 dropdown:标题可点击跳到第一个子页面,子项作为嵌套菜单
$firstChild = $children[0];
$parentParameters = [
'section' => $section['slug'],
'page' => $firstChild['slug'],
];
$sub->dropdown(
$page['title'],
function ($nested) use ($section, $children) {
foreach ($children as $childIndex => $child) {
$nested->route(
'business.pages.show',
$child['title'],
[
'section' => $section['slug'],
'page' => $child['slug'],
],
($childIndex + 1) * 10,
[
'icon' => '',
'active' => fn () => request()->route('section') === $section['slug']
&& request()->route('page') === $child['slug'],
]
);
}
},
($pageIndex + 1) * 10,
[
'icon' => '',
'active' => fn () => request()->route('section') === $section['slug']
&& in_array(request()->route('page'), array_column($children, 'slug'), true),
]
);
continue;
}
$sub->route(
'business.pages.show',
$page['title'],

View File

@ -58,7 +58,30 @@ class SidebarPermissions
}
$pages = array_values(array_filter($section['pages'] ?? [], function (array $page) use ($allowed, $sectionKey) {
return in_array($sectionKey . '/' . $page['slug'], $allowed, true);
$pageKey = $sectionKey . '/' . $page['slug'];
if (in_array($pageKey, $allowed, true)) {
// 若有 children,保留 children 的精确权限过滤
if (! empty($page['children'])) {
$page['children'] = array_values(array_filter($page['children'], function (array $child) use ($sectionKey) {
return in_array($sectionKey . '/' . $child['slug'], $allowed, true);
}));
}
return true;
}
// 子页面可能在 allowed 列表中(独立 URL),父级分组也允许展开
if (! empty($page['children'])) {
$visibleChildren = array_values(array_filter($page['children'], function (array $child) use ($sectionKey) {
return in_array($sectionKey . '/' . $child['slug'], $allowed, true);
}));
if (! empty($visibleChildren)) {
$page['children'] = $visibleChildren;
return true;
}
}
return false;
}));
if (! empty($pages)) {
@ -80,6 +103,10 @@ class SidebarPermissions
foreach ($section['pages'] ?? [] as $page) {
$keys[] = $section['slug'] . '/' . $page['slug'];
foreach ($page['children'] ?? [] as $child) {
$keys[] = $section['slug'] . '/' . $child['slug'];
}
}
}

View File

@ -153,7 +153,14 @@ return [
['slug' => 'advance-details', 'title' => '借支明细'],
['slug' => 'sample-deductions', 'title' => '样品扣款'],
['slug' => 'other-adjustments', 'title' => '其他扣款补款'],
['slug' => 'unpriced-details', 'title' => '未定价明细'],
[
'slug' => 'unpriced-details',
'title' => '未定价明细',
'children' => [
['slug' => 'delivery-unpriced', 'title' => '送货未定价'],
['slug' => 'return-unpriced', 'title' => '退货未定价'],
],
],
['slug' => 'dropshipping-express', 'title' => '代发快递'],
['slug' => 'supplier-payables-report', 'title' => '供应商应付表'],
],

View File

@ -132,6 +132,60 @@ class SupplierPayables extends ApiController
return response()->json($this->repo->filterOptionsForAdvance());
}
// ============================================================
// 送货未定价
// ============================================================
public function deliveryUnpricedIndex()
{
$filters = $this->filters('delivery-unpriced');
$result = $this->repo->deliveryUnpriced($filters, $this->page(), $this->limit());
return response()->json([
'data' => $result['data'],
'total' => $result['total'],
'page' => $this->page(),
'per_page' => $this->limit(),
'last_page' => (int) ceil(max($result['total'], 0) / $this->limit()),
]);
}
public function deliveryUnpricedSummary()
{
return response()->json($this->repo->deliveryUnpricedSummary($this->filters('delivery-unpriced')));
}
public function deliveryUnpricedOptions()
{
return response()->json($this->repo->filterOptionsForDeliveryUnpriced());
}
// ============================================================
// 退货未定价
// ============================================================
public function returnUnpricedIndex()
{
$filters = $this->filters('return-unpriced');
$result = $this->repo->returnUnpriced($filters, $this->page(), $this->limit());
return response()->json([
'data' => $result['data'],
'total' => $result['total'],
'page' => $this->page(),
'per_page' => $this->limit(),
'last_page' => (int) ceil(max($result['total'], 0) / $this->limit()),
]);
}
public function returnUnpricedSummary()
{
return response()->json($this->repo->returnUnpricedSummary($this->filters('return-unpriced')));
}
public function returnUnpricedOptions()
{
return response()->json($this->repo->filterOptionsForReturnUnpriced());
}
// ============================================================
// 样品扣款
// ============================================================
@ -159,6 +213,60 @@ class SupplierPayables extends ApiController
return response()->json($this->repo->filterOptionsForSample());
}
// ============================================================
// 其他扣款补款
// ============================================================
public function otherAdjustmentsIndex()
{
$filters = $this->filters('other-adjustments');
$result = $this->repo->otherAdjustments($filters, $this->page(), $this->limit());
return response()->json([
'data' => $result['data'],
'total' => $result['total'],
'page' => $this->page(),
'per_page' => $this->limit(),
'last_page' => (int) ceil(max($result['total'], 0) / $this->limit()),
]);
}
public function otherAdjustmentsSummary()
{
return response()->json($this->repo->otherAdjustmentsSummary($this->filters('other-adjustments')));
}
public function otherAdjustmentsOptions()
{
return response()->json($this->repo->filterOptionsForOtherAdjustments());
}
// ============================================================
// 代发快递
// ============================================================
public function dropshippingExpressIndex()
{
$filters = $this->filters('dropshipping-express');
$result = $this->repo->dropshippingExpress($filters, $this->page(), $this->limit());
return response()->json([
'data' => $result['data'],
'total' => $result['total'],
'page' => $this->page(),
'per_page' => $this->limit(),
'last_page' => (int) ceil(max($result['total'], 0) / $this->limit()),
]);
}
public function dropshippingExpressSummary()
{
return response()->json($this->repo->dropshippingExpressSummary($this->filters('dropshipping-express')));
}
public function dropshippingExpressOptions()
{
return response()->json($this->repo->filterOptionsForDropshippingExpress());
}
// ============================================================
// Helpers
// ============================================================
@ -167,7 +275,7 @@ class SupplierPayables extends ApiController
$filters = [];
// 通用文本字段
$text = ['supplier', 'warehouse', 'sku_id', 'express_no', 'creator', 'department'];
$text = ['supplier', 'warehouse', 'sku_id', 'express_no', 'creator', 'department', 'purchase', 'barcode', 'express_name'];
foreach ($text as $field) {
if ($val = request($field)) {
$filters[$field] = trim($val);

View File

@ -487,6 +487,171 @@ class SupplierPayableRepository
];
}
// ============================================================
// 6. 送货未定价 — pm_unOrderDetails (265452行)
// ============================================================
public function deliveryUnpriced(array $filters, int $page, int $pageSize): array
{
$where = [];
$params = [];
if (!empty($filters['supplier'])) {
$where[] = 'supplier LIKE ?';
$params[] = '%' . $filters['supplier'] . '%';
}
if (!empty($filters['warehouse'])) {
$where[] = 'warehouse LIKE ?';
$params[] = '%' . $filters['warehouse'] . '%';
}
if (!empty($filters['purchase'])) {
$where[] = 'purchase LIKE ?';
$params[] = '%' . $filters['purchase'] . '%';
}
if (!empty($filters['barcode'])) {
$where[] = 'barCode LIKE ?';
$params[] = '%' . $filters['barcode'] . '%';
}
if (!empty($filters['express_no'])) {
$where[] = 'expressNo LIKE ?';
$params[] = '%' . $filters['express_no'] . '%';
}
if (!empty($filters['date_from'])) {
$where[] = 'date >= ?';
$params[] = $filters['date_from'];
}
if (!empty($filters['date_to'])) {
$where[] = 'date <= ?';
$params[] = $filters['date_to'];
}
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
$sql = "SELECT
Id AS id,
CONVERT(varchar(10), date, 120) AS date,
purchase,
warehouse,
supplier,
transactionNo,
distributionNo,
expressNo,
sku,
barCode,
skuName,
CONVERT(varchar(19), distributionDate, 120) AS distribution_date,
CONVERT(varchar(10), shipDate, 120) AS ship_date,
expressName
FROM pm_unOrderDetails
$whereSql
ORDER BY date DESC, Id DESC";
return $this->runQuery($sql, $params, $page, $pageSize);
}
public function deliveryUnpricedSummary(array $filters): array
{
$where = [];
$params = [];
if (!empty($filters['supplier'])) {
$where[] = 'supplier LIKE ?';
$params[] = '%' . $filters['supplier'] . '%';
}
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
$sql = "SELECT COUNT(*) AS total_count FROM pm_unOrderDetails $whereSql";
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
$row = $stmt->fetch();
return [
'totalCount' => (int) $row['total_count'],
];
}
// ============================================================
// 7. 退货未定价 — finance_purchaseReturn WHERE priceB = 0 (35928行)
// ============================================================
public function returnUnpriced(array $filters, int $page, int $pageSize): array
{
$where = ['(priceB = 0 OR priceB IS NULL)'];
$params = [];
if (!empty($filters['supplier'])) {
$where[] = 'supplierName LIKE ?';
$params[] = '%' . $filters['supplier'] . '%';
}
if (!empty($filters['warehouse'])) {
$where[] = 'warehouseName LIKE ?';
$params[] = '%' . $filters['warehouse'] . '%';
}
if (!empty($filters['sku_id'])) {
$where[] = 'sku_id LIKE ?';
$params[] = '%' . $filters['sku_id'] . '%';
}
if (!empty($filters['express_no'])) {
$where[] = 'expressNo LIKE ?';
$params[] = '%' . $filters['express_no'] . '%';
}
if (!empty($filters['date_from'])) {
$where[] = 'date >= ?';
$params[] = $filters['date_from'];
}
if (!empty($filters['date_to'])) {
$where[] = 'date <= ?';
$params[] = $filters['date_to'];
}
$whereSql = 'WHERE ' . implode(' AND ', $where);
$sql = "SELECT
CONVERT(varchar(10), date, 120) AS send_time,
supplierName AS supplier,
sku_id AS barcode,
name AS sku_name,
CAST(qty AS decimal(18,2)) AS qty,
CAST(price AS decimal(18,2)) AS unit_price,
CAST(price * qty AS decimal(18,2)) AS amount,
CAST(ISNULL(priceB, 0) AS decimal(18,2)) AS guess_unit_price,
CAST(ISNULL(priceB, 0) * qty AS decimal(18,2)) AS guess_amount,
remark,
io_id AS wms_pick_no,
warehouseName AS warehouse,
expressNo AS express_no,
expressName AS express_name,
CONVERT(varchar(10), io_date, 120) AS io_date,
labels,
creator_name AS creator
FROM finance_purchaseReturn
$whereSql
ORDER BY date DESC";
return $this->runQuery($sql, $params, $page, $pageSize);
}
public function returnUnpricedSummary(array $filters): array
{
$where = ['(priceB = 0 OR priceB IS NULL)'];
$params = [];
if (!empty($filters['supplier'])) {
$where[] = 'supplierName LIKE ?';
$params[] = '%' . $filters['supplier'] . '%';
}
$whereSql = 'WHERE ' . implode(' AND ', $where);
$sql = "SELECT
ISNULL(SUM(price * qty), 0) AS total_amount,
COUNT(*) AS total_count
FROM finance_purchaseReturn $whereSql";
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
$row = $stmt->fetch();
return [
'totalAmount' => (float) $row['total_amount'],
'totalCount' => (int) $row['total_count'],
];
}
// ============================================================
// 筛选器选项
// ============================================================
@ -523,6 +688,23 @@ class SupplierPayableRepository
return ['suppliers' => $suppliers];
}
public function filterOptionsForDeliveryUnpriced(): array
{
$suppliers = $this->fetchDistinct('SELECT DISTINCT supplier FROM pm_unOrderDetails WHERE supplier IS NOT NULL ORDER BY supplier');
$warehouses = $this->fetchDistinct('SELECT DISTINCT warehouse FROM pm_unOrderDetails WHERE warehouse IS NOT NULL ORDER BY warehouse');
$purchases = $this->fetchDistinct('SELECT DISTINCT purchase FROM pm_unOrderDetails WHERE purchase IS NOT NULL ORDER BY purchase');
return compact('suppliers', 'warehouses', 'purchases');
}
public function filterOptionsForReturnUnpriced(): array
{
$suppliers = $this->fetchDistinct("SELECT DISTINCT supplierName FROM finance_purchaseReturn WHERE (priceB = 0 OR priceB IS NULL) AND supplierName IS NOT NULL ORDER BY supplierName");
$warehouses = $this->fetchDistinct("SELECT DISTINCT warehouseName FROM finance_purchaseReturn WHERE (priceB = 0 OR priceB IS NULL) AND warehouseName IS NOT NULL ORDER BY warehouseName");
return compact('suppliers', 'warehouses');
}
public function filterOptionsForSample(): array
{
$suppliers = $this->fetchDistinct('SELECT DISTINCT supplier FROM finance_sampleDeduction WHERE supplier IS NOT NULL ORDER BY supplier');
@ -537,4 +719,159 @@ class SupplierPayableRepository
$rows = $this->db->query($sql)->fetchAll(PDO::FETCH_COLUMN);
return array_values(array_filter($rows, fn ($v) => $v !== null && $v !== ''));
}
// ============================================================
// 8. 其他扣款补款 — fys_supplierPaymentSummary WHERE other != 0 (460行)
// ============================================================
public function otherAdjustments(array $filters, int $page, int $pageSize): array
{
$where = ['(other IS NOT NULL AND other != 0)'];
$params = [];
if (!empty($filters['supplier'])) {
$where[] = 'supplier LIKE ?';
$params[] = '%' . $filters['supplier'] . '%';
}
if (!empty($filters['month_from'])) {
$where[] = 'Month >= ?';
$params[] = $filters['month_from'];
}
if (!empty($filters['month_to'])) {
$where[] = 'Month <= ?';
$params[] = $filters['month_to'];
}
$whereSql = 'WHERE ' . implode(' AND ', $where);
$sql = "SELECT
'其他扣款补款' AS project,
Month AS month_str,
supplier,
CAST(other AS decimal(18,2)) AS supplement_amount,
reason AS supplement_reason,
remarks AS remark,
mark AS remark2,
checker AS person_charge
FROM fys_supplierPaymentSummary
$whereSql
ORDER BY Month DESC, supplier";
return $this->runQuery($sql, $params, $page, $pageSize);
}
public function otherAdjustmentsSummary(array $filters): array
{
$where = ['(other IS NOT NULL AND other != 0)'];
$params = [];
if (!empty($filters['supplier'])) {
$where[] = 'supplier LIKE ?';
$params[] = '%' . $filters['supplier'] . '%';
}
$whereSql = 'WHERE ' . implode(' AND ', $where);
$sql = "SELECT
ISNULL(SUM(other), 0) AS total_amount,
COUNT(*) AS total_count
FROM fys_supplierPaymentSummary $whereSql";
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
$row = $stmt->fetch();
return [
'totalAmount' => (float) $row['total_amount'],
'totalCount' => (int) $row['total_count'],
];
}
// ============================================================
// 9. 代发快递 — fys_express_courier_settlement (940行)
// ============================================================
public function dropshippingExpress(array $filters, int $page, int $pageSize): array
{
$where = ['(is_delete = 0 OR is_delete IS NULL)'];
$params = [];
if (!empty($filters['supplier'])) {
$where[] = 'courier_company_name LIKE ?';
$params[] = '%' . $filters['supplier'] . '%';
}
if (!empty($filters['express_name'])) {
$where[] = 'expressname LIKE ?';
$params[] = '%' . $filters['express_name'] . '%';
}
if (!empty($filters['month_from'])) {
$where[] = 'month >= ?';
$params[] = $filters['month_from'];
}
if (!empty($filters['month_to'])) {
$where[] = 'month <= ?';
$params[] = $filters['month_to'];
}
$whereSql = 'WHERE ' . implode(' AND ', $where);
$sql = "SELECT
reconciliation_person,
month AS month_str,
courier_company_name AS supplier,
CAST(ISNULL(waybill, 0) AS decimal(18,2)) AS express_freight,
CAST(ISNULL(courier_provided_amount, 0) AS decimal(18,2)) AS express_account,
CAST(ISNULL(replenish_courier, 0) AS decimal(18,2)) AS replenish_freight,
CAST(ISNULL(confirmed_amount, 0) AS decimal(18,2)) AS replenish_account,
CAST(ISNULL(reconciliation_difference, 0) AS decimal(18,2)) AS return_fee,
CAST(ISNULL(compensation_amount, 0) AS decimal(18,2)) AS intercept_fee,
CAST(ISNULL(other_replenishment, 0) AS decimal(18,2)) AS change_address_fee,
CAST(ISNULL(corporate_payment_amount, 0) AS decimal(18,2)) AS turnover_fee,
CAST(ISNULL(personal_payment_amount, 0) AS decimal(18,2)) AS overlong_fee,
CAST(ISNULL(payable_amount, 0) AS decimal(18,2)) AS total_freight,
status AS remark,
expressname AS express_name,
file_status AS remark2,
creator,
CONVERT(varchar(19), create_time, 120) AS create_time
FROM fys_express_courier_settlement
$whereSql
ORDER BY month DESC, expressname";
return $this->runQuery($sql, $params, $page, $pageSize);
}
public function dropshippingExpressSummary(array $filters): array
{
$where = ['(is_delete = 0 OR is_delete IS NULL)'];
$params = [];
if (!empty($filters['supplier'])) {
$where[] = 'courier_company_name LIKE ?';
$params[] = '%' . $filters['supplier'] . '%';
}
$whereSql = 'WHERE ' . implode(' AND ', $where);
$sql = "SELECT
ISNULL(SUM(payable_amount), 0) AS total_amount,
COUNT(*) AS total_count
FROM fys_express_courier_settlement $whereSql";
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
$row = $stmt->fetch();
return [
'totalAmount' => (float) $row['total_amount'],
'totalCount' => (int) $row['total_count'],
];
}
public function filterOptionsForOtherAdjustments(): array
{
$suppliers = $this->fetchDistinct("SELECT DISTINCT supplier FROM fys_supplierPaymentSummary WHERE (other IS NOT NULL AND other != 0) AND supplier IS NOT NULL ORDER BY supplier");
return ['suppliers' => $suppliers];
}
public function filterOptionsForDropshippingExpress(): array
{
$suppliers = $this->fetchDistinct("SELECT DISTINCT courier_company_name FROM fys_express_courier_settlement WHERE (is_delete = 0 OR is_delete IS NULL) AND courier_company_name IS NOT NULL ORDER BY courier_company_name");
$expressNames = $this->fetchDistinct("SELECT DISTINCT expressname FROM fys_express_courier_settlement WHERE (is_delete = 0 OR is_delete IS NULL) AND expressname IS NOT NULL ORDER BY expressname");
return compact('suppliers', 'expressNames');
}
}

View File

@ -8,4 +8,57 @@ Route::api('ecommerce-finance', function () {
Route::apiResource('stores', 'Stores')->except(['destroy']);
Route::apiResource('import-batches', 'ImportBatches')->only(['index', 'show', 'store']);
Route::get('reconciliation-exceptions', 'ReconciliationExceptions@index')->name('reconciliation-exceptions.index');
// 货款对账
Route::get('goods-reconciliations', 'GoodsReconciliations@index')->name('goods-reconciliations.index');
Route::get('goods-reconciliations/summary', 'GoodsReconciliations@summary')->name('goods-reconciliations.summary');
Route::get('goods-reconciliations/options', 'GoodsReconciliations@options')->name('goods-reconciliations.options');
// 供应商应付 - 子功能页面
Route::prefix('supplier-payables')->group(function () {
// 退货对账
Route::get('return-reconciliations', 'SupplierPayables@returnReconciliationsIndex');
Route::get('return-reconciliations/summary', 'SupplierPayables@returnReconciliationsSummary');
Route::get('return-reconciliations/options', 'SupplierPayables@returnReconciliationsOptions');
// 发票扣款
Route::get('invoice-deductions', 'SupplierPayables@invoiceDeductionsIndex');
Route::get('invoice-deductions/summary', 'SupplierPayables@invoiceDeductionsSummary');
Route::get('invoice-deductions/options', 'SupplierPayables@invoiceDeductionsOptions');
// 赔偿明细
Route::get('compensation-details', 'SupplierPayables@compensationDetailsIndex');
Route::get('compensation-details/summary', 'SupplierPayables@compensationDetailsSummary');
Route::get('compensation-details/options', 'SupplierPayables@compensationDetailsOptions');
// 借支明细
Route::get('advance-details', 'SupplierPayables@advanceDetailsIndex');
Route::get('advance-details/summary', 'SupplierPayables@advanceDetailsSummary');
Route::get('advance-details/options', 'SupplierPayables@advanceDetailsOptions');
// 送货未定价
Route::get('delivery-unpriced', 'SupplierPayables@deliveryUnpricedIndex');
Route::get('delivery-unpriced/summary', 'SupplierPayables@deliveryUnpricedSummary');
Route::get('delivery-unpriced/options', 'SupplierPayables@deliveryUnpricedOptions');
// 退货未定价
Route::get('return-unpriced', 'SupplierPayables@returnUnpricedIndex');
Route::get('return-unpriced/summary', 'SupplierPayables@returnUnpricedSummary');
Route::get('return-unpriced/options', 'SupplierPayables@returnUnpricedOptions');
// 样品扣款
Route::get('sample-deductions', 'SupplierPayables@sampleDeductionsIndex');
Route::get('sample-deductions/summary', 'SupplierPayables@sampleDeductionsSummary');
Route::get('sample-deductions/options', 'SupplierPayables@sampleDeductionsOptions');
// 其他扣款补款
Route::get('other-adjustments', 'SupplierPayables@otherAdjustmentsIndex');
Route::get('other-adjustments/summary', 'SupplierPayables@otherAdjustmentsSummary');
Route::get('other-adjustments/options', 'SupplierPayables@otherAdjustmentsOptions');
// 代发快递
Route::get('dropshipping-express', 'SupplierPayables@dropshippingExpressIndex');
Route::get('dropshipping-express/summary', 'SupplierPayables@dropshippingExpressSummary');
Route::get('dropshipping-express/options', 'SupplierPayables@dropshippingExpressOptions');
});
});

View File

@ -0,0 +1,105 @@
require('./../../bootstrap');
import Vue from 'vue';
import DashboardPlugin from './../../plugins/dashboard-plugin';
import Global from './../../mixins/global';
import {
Table, TableColumn, Pagination, DatePicker, Tag, Button, Input, Select, Option, Message
} from 'element-ui';
Vue.use(DashboardPlugin);
Vue.component(Table.name, Table);
Vue.component(TableColumn.name, TableColumn);
Vue.component(Pagination.name, Pagination);
Vue.component(DatePicker.name, DatePicker);
Vue.component(Tag.name, Tag);
Vue.component(Input.name, Input);
Vue.component(Button.name, Button);
Vue.component(Select.name, Select);
Vue.component(Option.name, Option);
Vue.prototype.$message = Message;
const app = new Vue({
el: '#delivery-unpriced-app',
mixins: [Global],
data() {
return {
baseUrl: url + '/api/ecommerce-finance/supplier-payables/delivery-unpriced',
loading: false,
tableData: [],
total: 0,
currentPage: 1,
pageSize: 25,
summary: { totalCount: 0 },
options: { suppliers: [], warehouses: [], purchases: [] },
filters: {
supplier: '',
warehouse: '',
purchase: '',
barcode: '',
express_no: '',
date_range: null
}
};
},
mounted() {
this.fetchOptions();
this.fetchData();
},
methods: {
fetchOptions() {
axios.get(this.baseUrl + '/options')
.then(r => { this.options = r.data; })
.catch(() => this.$message.error('获取筛选选项失败'));
},
fetchData() {
this.loading = true;
const params = this.buildParams();
Promise.all([
axios.get(this.baseUrl, { params }),
axios.get(this.baseUrl + '/summary', { params })
]).then(([listRes, sumRes]) => {
this.tableData = listRes.data.data || [];
this.total = listRes.data.total || 0;
this.currentPage = listRes.data.page || 1;
this.pageSize = listRes.data.per_page || 25;
this.summary = sumRes.data;
}).catch(() => this.$message.error('获取数据失败'))
.finally(() => { this.loading = false; });
},
buildParams() {
const params = { page: this.currentPage, limit: this.pageSize };
['supplier', 'warehouse', 'purchase', 'barcode', 'express_no'].forEach(f => {
if (this.filters[f]) params[f] = this.filters[f];
});
if (this.filters.date_range && this.filters.date_range.length === 2) {
params.date_from = this.filters.date_range[0];
params.date_to = this.filters.date_range[1];
}
return params;
},
onFilterChange() { this.currentPage = 1; this.fetchData(); },
onPageChange(p) { this.currentPage = p; this.fetchData(); },
onPageSizeChange(s) { this.pageSize = s; this.currentPage = 1; this.fetchData(); },
onReset() {
this.filters = { supplier: '', warehouse: '', purchase: '', barcode: '', express_no: '', date_range: null };
this.currentPage = 1;
this.fetchData();
},
formatMoney(v) {
if (v == null || isNaN(v)) return '0.00';
return '¥' + Number(v).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
}
});
export default app;

View File

@ -0,0 +1,97 @@
require('./../../bootstrap');
import Vue from 'vue';
import DashboardPlugin from './../../plugins/dashboard-plugin';
import Global from './../../mixins/global';
import {
Table, TableColumn, Pagination, DatePicker, Tag, Button, Input, Select, Option, Message
} from 'element-ui';
Vue.use(DashboardPlugin);
Vue.component(Table.name, Table);
Vue.component(TableColumn.name, TableColumn);
Vue.component(Pagination.name, Pagination);
Vue.component(DatePicker.name, DatePicker);
Vue.component(Tag.name, Tag);
Vue.component(Input.name, Input);
Vue.component(Button.name, Button);
Vue.component(Select.name, Select);
Vue.component(Option.name, Option);
Vue.prototype.$message = Message;
const app = new Vue({
el: '#dropshipping-express-app',
mixins: [Global],
data() {
return {
baseUrl: url + '/api/ecommerce-finance/supplier-payables/dropshipping-express',
loading: false,
tableData: [],
total: 0,
currentPage: 1,
pageSize: 25,
summary: { totalAmount: 0, totalCount: 0 },
options: { suppliers: [], expressNames: [] },
filters: { supplier: '', express_name: '', month_range: null }
};
},
mounted() {
this.fetchOptions();
this.fetchData();
},
methods: {
fetchOptions() {
axios.get(this.baseUrl + '/options')
.then(r => { this.options = r.data; })
.catch(() => this.$message.error('获取筛选选项失败'));
},
fetchData() {
this.loading = true;
const params = this.buildParams();
Promise.all([
axios.get(this.baseUrl, { params }),
axios.get(this.baseUrl + '/summary', { params })
]).then(([listRes, sumRes]) => {
this.tableData = listRes.data.data || [];
this.total = listRes.data.total || 0;
this.currentPage = listRes.data.page || 1;
this.pageSize = listRes.data.per_page || 25;
this.summary = sumRes.data;
}).catch(() => this.$message.error('获取数据失败'))
.finally(() => { this.loading = false; });
},
buildParams() {
const params = { page: this.currentPage, limit: this.pageSize };
if (this.filters.supplier) params.supplier = this.filters.supplier;
if (this.filters.express_name) params.express_name = this.filters.express_name;
if (this.filters.month_range && this.filters.month_range.length === 2) {
params.month_from = this.filters.month_range[0];
params.month_to = this.filters.month_range[1];
}
return params;
},
onFilterChange() { this.currentPage = 1; this.fetchData(); },
onPageChange(p) { this.currentPage = p; this.fetchData(); },
onPageSizeChange(s) { this.pageSize = s; this.currentPage = 1; this.fetchData(); },
onReset() {
this.filters = { supplier: '', express_name: '', month_range: null };
this.currentPage = 1;
this.fetchData();
},
formatMoney(v) {
if (v == null || isNaN(v)) return '0.00';
return '¥' + Number(v).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
}
});
export default app;

View File

@ -0,0 +1,84 @@
require('./../../bootstrap');
import Vue from 'vue';
import DashboardPlugin from './../../plugins/dashboard-plugin';
import Global from './../../mixins/global';
import {
Table, TableColumn, Pagination, DatePicker, Tag, Button, Input, Message
} from 'element-ui';
Vue.use(DashboardPlugin);
Vue.component(Table.name, Table);
Vue.component(TableColumn.name, TableColumn);
Vue.component(Pagination.name, Pagination);
Vue.component(DatePicker.name, DatePicker);
Vue.component(Tag.name, Tag);
Vue.component(Input.name, Input);
Vue.component(Button.name, Button);
Vue.prototype.$message = Message;
const app = new Vue({
el: '#other-adjustment-app',
mixins: [Global],
data() {
return {
baseUrl: url + '/api/ecommerce-finance/supplier-payables/other-adjustments',
loading: false,
tableData: [],
total: 0,
currentPage: 1,
pageSize: 25,
summary: { totalAmount: 0, totalCount: 0 },
filters: { supplier: '', month_range: null }
};
},
mounted() { this.fetchData(); },
methods: {
fetchData() {
this.loading = true;
const params = this.buildParams();
Promise.all([
axios.get(this.baseUrl, { params }),
axios.get(this.baseUrl + '/summary', { params })
]).then(([listRes, sumRes]) => {
this.tableData = listRes.data.data || [];
this.total = listRes.data.total || 0;
this.currentPage = listRes.data.page || 1;
this.pageSize = listRes.data.per_page || 25;
this.summary = sumRes.data;
}).catch(() => this.$message.error('获取数据失败'))
.finally(() => { this.loading = false; });
},
buildParams() {
const params = { page: this.currentPage, limit: this.pageSize };
if (this.filters.supplier) params.supplier = this.filters.supplier;
if (this.filters.month_range && this.filters.month_range.length === 2) {
params.month_from = this.filters.month_range[0];
params.month_to = this.filters.month_range[1];
}
return params;
},
onFilterChange() { this.currentPage = 1; this.fetchData(); },
onPageChange(p) { this.currentPage = p; this.fetchData(); },
onPageSizeChange(s) { this.pageSize = s; this.currentPage = 1; this.fetchData(); },
onReset() {
this.filters = { supplier: '', month_range: null };
this.currentPage = 1;
this.fetchData();
},
formatMoney(v) {
if (v == null || isNaN(v)) return '0.00';
return '¥' + Number(v).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
}
});
export default app;

View File

@ -0,0 +1,104 @@
require('./../../bootstrap');
import Vue from 'vue';
import DashboardPlugin from './../../plugins/dashboard-plugin';
import Global from './../../mixins/global';
import {
Table, TableColumn, Pagination, DatePicker, Tag, Button, Input, Select, Option, Message
} from 'element-ui';
Vue.use(DashboardPlugin);
Vue.component(Table.name, Table);
Vue.component(TableColumn.name, TableColumn);
Vue.component(Pagination.name, Pagination);
Vue.component(DatePicker.name, DatePicker);
Vue.component(Tag.name, Tag);
Vue.component(Input.name, Input);
Vue.component(Button.name, Button);
Vue.component(Select.name, Select);
Vue.component(Option.name, Option);
Vue.prototype.$message = Message;
const app = new Vue({
el: '#return-unpriced-app',
mixins: [Global],
data() {
return {
baseUrl: url + '/api/ecommerce-finance/supplier-payables/return-unpriced',
loading: false,
tableData: [],
total: 0,
currentPage: 1,
pageSize: 25,
summary: { totalAmount: 0, totalCount: 0 },
options: { suppliers: [], warehouses: [] },
filters: {
supplier: '',
warehouse: '',
sku_id: '',
express_no: '',
date_range: null
}
};
},
mounted() {
this.fetchOptions();
this.fetchData();
},
methods: {
fetchOptions() {
axios.get(this.baseUrl + '/options')
.then(r => { this.options = r.data; })
.catch(() => this.$message.error('获取筛选选项失败'));
},
fetchData() {
this.loading = true;
const params = this.buildParams();
Promise.all([
axios.get(this.baseUrl, { params }),
axios.get(this.baseUrl + '/summary', { params })
]).then(([listRes, sumRes]) => {
this.tableData = listRes.data.data || [];
this.total = listRes.data.total || 0;
this.currentPage = listRes.data.page || 1;
this.pageSize = listRes.data.per_page || 25;
this.summary = sumRes.data;
}).catch(() => this.$message.error('获取数据失败'))
.finally(() => { this.loading = false; });
},
buildParams() {
const params = { page: this.currentPage, limit: this.pageSize };
['supplier', 'warehouse', 'sku_id', 'express_no'].forEach(f => {
if (this.filters[f]) params[f] = this.filters[f];
});
if (this.filters.date_range && this.filters.date_range.length === 2) {
params.date_from = this.filters.date_range[0];
params.date_to = this.filters.date_range[1];
}
return params;
},
onFilterChange() { this.currentPage = 1; this.fetchData(); },
onPageChange(p) { this.currentPage = p; this.fetchData(); },
onPageSizeChange(s) { this.pageSize = s; this.currentPage = 1; this.fetchData(); },
onReset() {
this.filters = { supplier: '', warehouse: '', sku_id: '', express_no: '', date_range: null };
this.currentPage = 1;
this.fetchData();
},
formatMoney(v) {
if (v == null || isNaN(v)) return '0.00';
return '¥' + Number(v).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
}
});
export default app;

View File

@ -0,0 +1,78 @@
<div id="delivery-unpriced-app" class="delivery-unpriced-page">
<div v-cloak>
{{-- 统计卡片 --}}
<div class="grid grid-cols-2 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-orange-500">@{{ (summary.totalCount || 0).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-base font-medium text-gray-700 mt-2">pm_unOrderDetails</div>
<div class="text-xs text-gray-400 mt-1">代发订单中未定价的明细记录</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">
<el-input v-model="filters.supplier" placeholder="供应商" size="small" style="width: 160px" clearable @clear="onFilterChange" @keyup.enter="onFilterChange"></el-input>
<el-select v-model="filters.warehouse" placeholder="仓库" size="small" style="width: 180px" filterable clearable @change="onFilterChange">
<el-option v-for="w in options.warehouses" :key="w" :label="w" :value="w"></el-option>
</el-select>
<el-select v-model="filters.purchase" placeholder="采购人" size="small" style="width: 120px" filterable clearable @change="onFilterChange">
<el-option v-for="p in options.purchases" :key="p" :label="p" :value="p"></el-option>
</el-select>
<el-input v-model="filters.barcode" placeholder="商品编码" size="small" style="width: 160px" clearable @clear="onFilterChange" @keyup.enter="onFilterChange"></el-input>
<el-input v-model="filters.express_no" placeholder="快递单号" size="small" style="width: 160px" clearable @clear="onFilterChange" @keyup.enter="onFilterChange"></el-input>
<el-date-picker v-model="filters.date_range" type="daterange"
start-placeholder="日期开始" end-placeholder="日期结束" size="small"
style="width: 260px" value-format="yyyy-MM-dd" @change="onFilterChange">
</el-date-picker>
<el-button size="small" type="primary" @click="onFilterChange">查询</el-button>
<el-button size="small" @click="onReset">重置</el-button>
</div>
</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" height="600">
<el-table-column type="index" label="#" width="50" fixed="left"></el-table-column>
<el-table-column prop="date" label="日期" width="110" fixed="left"></el-table-column>
<el-table-column prop="purchase" label="采购人" width="100" show-overflow-tooltip></el-table-column>
<el-table-column prop="warehouse" label="仓库" width="180" show-overflow-tooltip></el-table-column>
<el-table-column prop="supplier" label="供应商" width="120" show-overflow-tooltip></el-table-column>
<el-table-column prop="transactionNo" label="交易号" width="200" show-overflow-tooltip></el-table-column>
<el-table-column prop="distributionNo" label="配货单号" width="200" show-overflow-tooltip></el-table-column>
<el-table-column prop="expressNo" label="快递单号" width="160" show-overflow-tooltip></el-table-column>
<el-table-column prop="sku" label="SKU编码" width="120" show-overflow-tooltip></el-table-column>
<el-table-column prop="barCode" label="条形码" width="160" show-overflow-tooltip></el-table-column>
<el-table-column prop="skuName" label="商品名称" width="240" show-overflow-tooltip></el-table-column>
<el-table-column prop="distribution_date" label="配货时间" width="160" show-overflow-tooltip></el-table-column>
<el-table-column prop="ship_date" label="发货时间" width="110"></el-table-column>
<el-table-column prop="expressName" label="快递名称" width="100" show-overflow-tooltip></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/delivery-unpriced.min.js') }}"></script>
@endpush

View File

@ -0,0 +1,101 @@
<div id="dropshipping-express-app" class="dropshipping-express-page">
<div v-cloak>
{{-- 统计卡片 --}}
<div class="grid grid-cols-2 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-red-600">@{{ 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-indigo-600">@{{ (summary.totalCount || 0).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">
<el-input v-model="filters.supplier" placeholder="供应商" size="small" style="width: 160px" clearable @clear="onFilterChange" @keyup.enter="onFilterChange"></el-input>
<el-select v-model="filters.express_name" placeholder="快递" size="small" style="width: 180px" filterable clearable @change="onFilterChange">
<el-option v-for="e in options.expressNames" :key="e" :label="e" :value="e"></el-option>
</el-select>
<el-date-picker v-model="filters.month_range" type="monthrange"
start-placeholder="月份开始" end-placeholder="月份结束" size="small"
style="width: 240px" value-format="yyyy-MM" @change="onFilterChange">
</el-date-picker>
<el-button size="small" type="primary" @click="onFilterChange">查询</el-button>
<el-button size="small" @click="onReset">重置</el-button>
</div>
</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" height="600">
<el-table-column type="index" label="#" width="50" fixed="left"></el-table-column>
<el-table-column prop="reconciliation_person" label="对账人" width="100" fixed="left"></el-table-column>
<el-table-column prop="month_str" label="日期" width="100"></el-table-column>
<el-table-column prop="supplier" label="供应商" width="120" show-overflow-tooltip></el-table-column>
<el-table-column label="快递运费" width="120" align="right">
<template slot-scope="scope">@{{ formatMoney(scope.row.express_freight) }}</template>
</el-table-column>
<el-table-column label="快递记账" width="120" align="right">
<template slot-scope="scope">@{{ formatMoney(scope.row.express_account) }}</template>
</el-table-column>
<el-table-column label="补运费" width="110" align="right">
<template slot-scope="scope">@{{ formatMoney(scope.row.replenish_freight) }}</template>
</el-table-column>
<el-table-column label="补记账" width="110" align="right">
<template slot-scope="scope">@{{ formatMoney(scope.row.replenish_account) }}</template>
</el-table-column>
<el-table-column label="退回费" width="110" align="right">
<template slot-scope="scope">
<span :class="scope.row.return_fee < 0 ? 'text-red-600' : ''">@{{ formatMoney(scope.row.return_fee) }}</span>
</template>
</el-table-column>
<el-table-column label="拦截" width="100" align="right">
<template slot-scope="scope">@{{ formatMoney(scope.row.intercept_fee) }}</template>
</el-table-column>
<el-table-column label="改地址" width="100" align="right">
<template slot-scope="scope">@{{ formatMoney(scope.row.change_address_fee) }}</template>
</el-table-column>
<el-table-column label="翻箱费" width="100" align="right">
<template slot-scope="scope">@{{ formatMoney(scope.row.turnover_fee) }}</template>
</el-table-column>
<el-table-column label="超长费" width="100" align="right">
<template slot-scope="scope">@{{ formatMoney(scope.row.overlong_fee) }}</template>
</el-table-column>
<el-table-column label="合计运费" width="130" align="right">
<template slot-scope="scope">
<span class="font-bold text-gray-800">@{{ formatMoney(scope.row.total_freight) }}</span>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" width="120" show-overflow-tooltip></el-table-column>
<el-table-column prop="express_name" label="快递" width="160" show-overflow-tooltip></el-table-column>
<el-table-column prop="remark2" label="备注" width="120" show-overflow-tooltip>
<template slot-scope="scope"><span class="text-gray-400">@{{ scope.row.remark2 || '-' }}</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/dropshipping-express.min.js') }}"></script>
@endpush

View File

@ -0,0 +1,80 @@
<div id="other-adjustment-app" class="other-adjustment-page">
<div v-cloak>
{{-- 统计卡片 --}}
<div class="grid grid-cols-2 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-red-600">@{{ 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-indigo-600">@{{ (summary.totalCount || 0).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">
<el-input v-model="filters.supplier" placeholder="厂家" size="small" style="width: 200px" clearable @clear="onFilterChange" @keyup.enter="onFilterChange"></el-input>
<el-date-picker v-model="filters.month_range" type="monthrange"
start-placeholder="月份开始" end-placeholder="月份结束" size="small"
style="width: 240px" value-format="yyyy-MM" @change="onFilterChange">
</el-date-picker>
<el-button size="small" type="primary" @click="onFilterChange">查询</el-button>
<el-button size="small" @click="onReset">重置</el-button>
</div>
</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" height="600">
<el-table-column type="index" label="#" width="50" fixed="left"></el-table-column>
<el-table-column prop="project" label="项目" width="140" fixed="left">
<template slot-scope="scope">
<el-tag size="mini" type="info">@{{ scope.row.project }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="month_str" label="日期" width="100"></el-table-column>
<el-table-column prop="supplier" label="厂家" width="160" show-overflow-tooltip></el-table-column>
<el-table-column prop="supplement_amount" label="补款金额" width="140" align="right">
<template slot-scope="scope">
<span :class="scope.row.supplement_amount < 0 ? 'text-red-600' : 'text-green-600'">@{{ formatMoney(scope.row.supplement_amount) }}</span>
</template>
</el-table-column>
<el-table-column prop="supplement_reason" label="补款原因" width="200" show-overflow-tooltip>
<template slot-scope="scope"><span class="text-gray-600">@{{ scope.row.supplement_reason || '-' }}</span></template>
</el-table-column>
<el-table-column prop="remark" label="备注" width="180" show-overflow-tooltip>
<template slot-scope="scope"><span class="text-gray-400">@{{ scope.row.remark || '-' }}</span></template>
</el-table-column>
<el-table-column prop="remark2" label="备注2" width="180" show-overflow-tooltip>
<template slot-scope="scope"><span class="text-gray-400">@{{ scope.row.remark2 || '-' }}</span></template>
</el-table-column>
<el-table-column prop="person_charge" label="负责人" width="100" show-overflow-tooltip>
<template slot-scope="scope"><span class="text-gray-400">@{{ scope.row.person_charge || '-' }}</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/other-adjustments.min.js') }}"></script>
@endpush

View File

@ -0,0 +1,100 @@
<div id="return-unpriced-app" class="return-unpriced-page">
<div v-cloak>
<div class="bg-blue-50 border border-blue-200 rounded-lg p-3 mb-4 text-sm text-blue-800">
<i class="el-icon-info mr-1"></i>
数据源:<code class="bg-white px-1 rounded">finance_purchaseReturn</code> 中 <code class="bg-white px-1 rounded">priceB = 0</code> 的记录(预估单价未维护),共 35,928 条。
</div>
{{-- 统计卡片 --}}
<div class="grid grid-cols-2 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-orange-500">@{{ 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">@{{ (summary.totalCount || 0).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">
<el-input v-model="filters.supplier" placeholder="供应商" size="small" style="width: 160px" clearable @clear="onFilterChange" @keyup.enter="onFilterChange"></el-input>
<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.sku_id" placeholder="条形码" size="small" style="width: 160px" clearable @clear="onFilterChange" @keyup.enter="onFilterChange"></el-input>
<el-input v-model="filters.express_no" placeholder="快递单号" size="small" style="width: 160px" clearable @clear="onFilterChange" @keyup.enter="onFilterChange"></el-input>
<el-date-picker v-model="filters.date_range" type="daterange"
start-placeholder="日期开始" end-placeholder="日期结束" size="small"
style="width: 260px" value-format="yyyy-MM-dd" @change="onFilterChange">
</el-date-picker>
<el-button size="small" type="primary" @click="onFilterChange">查询</el-button>
<el-button size="small" @click="onReset">重置</el-button>
</div>
</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" height="600">
<el-table-column type="index" label="#" width="50" fixed="left"></el-table-column>
<el-table-column prop="send_time" label="发货时间" width="110" fixed="left"></el-table-column>
<el-table-column prop="supplier" label="供应商" width="120" show-overflow-tooltip></el-table-column>
<el-table-column prop="barcode" label="条形码" width="160" show-overflow-tooltip></el-table-column>
<el-table-column prop="sku_name" label="商品名称" width="220" 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.unit_price) }}</template>
</el-table-column>
<el-table-column label="金额" width="110" 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">
<span class="text-orange-500">@{{ formatMoney(scope.row.guess_unit_price) }}</span>
</template>
</el-table-column>
<el-table-column label="预估金额" width="110" align="right">
<template slot-scope="scope">
<span class="text-orange-500">@{{ formatMoney(scope.row.guess_amount) }}</span>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" width="160" show-overflow-tooltip></el-table-column>
<el-table-column prop="wms_pick_no" label="wms配货单号" width="120" show-overflow-tooltip></el-table-column>
<el-table-column prop="warehouse" label="仓库名称" width="140" show-overflow-tooltip></el-table-column>
<el-table-column prop="express_no" label="快递单号" width="140" show-overflow-tooltip></el-table-column>
<el-table-column prop="express_name" label="快递名称" width="100" show-overflow-tooltip></el-table-column>
<el-table-column prop="io_date" label="出库时间" width="110"></el-table-column>
<el-table-column prop="labels" label="标记多标签" width="120">
<template slot-scope="scope">
<el-tag v-if="scope.row.labels" size="mini" type="warning">@{{ scope.row.labels }}</el-tag>
<span v-else class="text-gray-400">-</span>
</template>
</el-table-column>
<el-table-column prop="creator" label="创建人" width="100" show-overflow-tooltip></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/return-unpriced.min.js') }}"></script>
@endpush

12
webpack.mix.js vendored
View File

@ -64,6 +64,18 @@ mix
// Business workspace(店铺管理 › 各子功能)
.js('resources/assets/js/views/business/pages.js', 'public/js/business/pages.min.js')
// Ecommerce Finance
.js('resources/assets/js/views/ecommerce-finance/goods-reconciliations.js', 'public/js/ecommerce-finance/goods-reconciliations.min.js')
.js('resources/assets/js/views/ecommerce-finance/return-reconciliations.js', 'public/js/ecommerce-finance/return-reconciliations.min.js')
.js('resources/assets/js/views/ecommerce-finance/invoice-deductions.js', 'public/js/ecommerce-finance/invoice-deductions.min.js')
.js('resources/assets/js/views/ecommerce-finance/compensation-details.js', 'public/js/ecommerce-finance/compensation-details.min.js')
.js('resources/assets/js/views/ecommerce-finance/advance-details.js', 'public/js/ecommerce-finance/advance-details.min.js')
.js('resources/assets/js/views/ecommerce-finance/sample-deductions.js', 'public/js/ecommerce-finance/sample-deductions.min.js')
.js('resources/assets/js/views/ecommerce-finance/delivery-unpriced.js', 'public/js/ecommerce-finance/delivery-unpriced.min.js')
.js('resources/assets/js/views/ecommerce-finance/return-unpriced.js', 'public/js/ecommerce-finance/return-unpriced.min.js')
.js('resources/assets/js/views/ecommerce-finance/other-adjustments.js', 'public/js/ecommerce-finance/other-adjustments.min.js')
.js('resources/assets/js/views/ecommerce-finance/dropshipping-express.js', 'public/js/ecommerce-finance/dropshipping-express.min.js')
// Portal
.js('resources/assets/js/views/portal/apps.js', 'public/js/portal/apps.min.js')