fix: 修复淘系微信账单加载和表头
This commit is contained in:
parent
c6945fd188
commit
db0063f78b
@ -8,6 +8,7 @@ namespace Modules\EcommerceFinance;
|
||||
* 列定义来自「账单抬头.xlsx」的各子表(sheet 名 = 账户类型)。
|
||||
* sheet 名 ↔ tab slug ↔ 列 三者在此一一对应,避免错乱。
|
||||
*
|
||||
* 账户可选配置分组表头 groups,字段列统一由 columns 定义。
|
||||
* 每列: [label, field, kind]
|
||||
* field: 真实列名(如 record_code / income / occurred_at / updated_at),
|
||||
* 或 'payload.xxx' 表示存在 payload JSON 中。
|
||||
@ -18,13 +19,20 @@ namespace Modules\EcommerceFinance;
|
||||
class AccountBillColumns
|
||||
{
|
||||
/**
|
||||
* @return array<string,array{title:string,columns:array<int,array{0:string,1:string,2:string}>}>
|
||||
* @return array<string,array{title:string,groups?:array<int,array{0:string,1:int}>,columns:array<int,array{0:string,1:string,2:string}>}>
|
||||
*/
|
||||
public static function map(): array
|
||||
{
|
||||
return [
|
||||
'taobao-wechat' => [
|
||||
'title' => '淘系微信账户',
|
||||
'groups' => [
|
||||
['基础信息', 7],
|
||||
['账户与交易', 5],
|
||||
['金额', 2],
|
||||
['业务关联', 2],
|
||||
['维护信息', 2],
|
||||
],
|
||||
'columns' => [
|
||||
['记录编码', 'record_code', 'num'],
|
||||
['店铺', 'store_name', 'text'],
|
||||
@ -214,7 +222,7 @@ class AccountBillColumns
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{title:string,columns:array<int,array{label:string,field:string,kind:string}>}
|
||||
* @return array{title:string,groups:array<int,array{label:string,span:int}>,columns:array<int,array{label:string,field:string,kind:string}>}
|
||||
*/
|
||||
public static function for(string $type): ?array
|
||||
{
|
||||
@ -228,8 +236,13 @@ class AccountBillColumns
|
||||
return ['label' => $c[0], 'field' => $c[1], 'kind' => $c[2]];
|
||||
}, $map[$type]['columns']);
|
||||
|
||||
$groups = array_map(function ($group) {
|
||||
return ['label' => $group[0], 'span' => $group[1]];
|
||||
}, $map[$type]['groups'] ?? []);
|
||||
|
||||
return [
|
||||
'title' => $map[$type]['title'],
|
||||
'groups' => $groups,
|
||||
'columns' => $columns,
|
||||
];
|
||||
}
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
|
||||
namespace Modules\EcommerceFinance\Http\Controllers;
|
||||
|
||||
use App\Abstracts\Http\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Modules\EcommerceFinance\AccountBillColumns;
|
||||
use Modules\EcommerceFinance\Models\AccountBill;
|
||||
|
||||
@ -14,9 +14,9 @@ class AccountBills extends Controller
|
||||
* 经 admin 路由组(web 会话)暴露,前端带 CSRF 调用。
|
||||
* 按 bill_type 过滤,返回分页数据 + 汇总 + 该类型的列配置。
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request, string $bill_type)
|
||||
{
|
||||
$billType = (string) $request->get('bill_type', '');
|
||||
$billType = $bill_type;
|
||||
|
||||
if (! AccountBillColumns::has($billType)) {
|
||||
abort(404, '未知的账户类型。');
|
||||
|
||||
@ -9,7 +9,4 @@ Route::admin('ecommerce-finance', function () {
|
||||
Route::get('alipay-bills', 'AlipayBills@index')->name('alipay-bills.index');
|
||||
Route::get('alipay-bills/{bill}', 'AlipayBills@show')->name('alipay-bills.show');
|
||||
|
||||
// 店铺收款账户账单 › 其它账户类型(通用表 ec_account_bills,按 bill_type 区分)
|
||||
Route::get('account-bills', 'AccountBills@index')->name('account-bills.index');
|
||||
Route::get('account-bills/{bill}', 'AccountBills@show')->name('account-bills.show');
|
||||
});
|
||||
|
||||
@ -54,15 +54,20 @@
|
||||
<!-- 数据表(列由后端配置动态渲染) -->
|
||||
<div class="ab-panel">
|
||||
<div class="ab-phead">
|
||||
<div class="ab-title">{{ columnsTitle }}</div>
|
||||
<div class="ab-title">{{ columnGroups.length ? '账单明细' : columnsTitle }}</div>
|
||||
<div class="ab-count" v-if="!loading">{{ total }} 条</div>
|
||||
</div>
|
||||
|
||||
<div class="ab-scroll">
|
||||
<table class="ab-table" v-if="!loading && columns.length">
|
||||
<table class="ab-table" :class="{ 'ab-table-grouped': columnGroups.length }" v-if="!loading && !loadError && columns.length">
|
||||
<thead>
|
||||
<tr>
|
||||
<th v-for="(c, i) in columns" :key="i" :class="{ 'ab-num': isNumKind(c.kind) }"
|
||||
<tr class="ab-group" v-if="columnGroups.length">
|
||||
<th v-for="(group, i) in columnGroups" :key="i" :colspan="group.span" scope="colgroup">
|
||||
{{ group.label }}
|
||||
</th>
|
||||
</tr>
|
||||
<tr class="ab-col">
|
||||
<th v-for="(c, i) in columns" :key="i" :class="{ 'ab-num': isNumKind(c.kind) }" scope="col"
|
||||
@click="maybeSort(c)">
|
||||
{{ c.label }}
|
||||
<span class="ab-sort" v-if="sortableField(c.field)">⇅</span>
|
||||
@ -82,7 +87,12 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div v-else class="ab-empty">加载中…</div>
|
||||
<div v-else-if="loading" class="ab-empty">加载中…</div>
|
||||
<div v-else-if="loadError" class="ab-empty ab-error">
|
||||
<div>账单加载失败,请重试</div>
|
||||
<button class="ab-btn" @click="fetch">重新加载</button>
|
||||
</div>
|
||||
<div v-else class="ab-empty">暂无账单字段</div>
|
||||
</div>
|
||||
|
||||
<!-- 分页 -->
|
||||
@ -120,9 +130,11 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
loadError: false,
|
||||
rows: [],
|
||||
columns: [],
|
||||
columnsTitle: '',
|
||||
columnGroups: [],
|
||||
summary: { income: 0, expense: 0, balance: 0, count: 0 },
|
||||
total: 0,
|
||||
currentPage: 1,
|
||||
@ -149,8 +161,8 @@ export default {
|
||||
methods: {
|
||||
async fetch() {
|
||||
this.loading = true;
|
||||
this.loadError = false;
|
||||
const params = {
|
||||
bill_type: this.billType,
|
||||
...this.filters,
|
||||
sort: this.sort.key,
|
||||
dir: this.sort.dir,
|
||||
@ -170,12 +182,17 @@ export default {
|
||||
if (body.columns) {
|
||||
this.columns = body.columns.columns || body.columns || [];
|
||||
this.columnsTitle = body.columns.title || '';
|
||||
this.columnGroups = body.columns.groups || [];
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载账单失败', e);
|
||||
this.rows = [];
|
||||
this.columns = [];
|
||||
this.columnsTitle = '';
|
||||
this.columnGroups = [];
|
||||
this.total = 0;
|
||||
this.summary = { income: 0, expense: 0, balance: 0, count: 0 };
|
||||
this.loadError = true;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
@ -297,8 +314,10 @@ export default {
|
||||
|
||||
.ab-scroll { overflow-x: auto; }
|
||||
.ab-table { border-collapse: collapse; width: 100%; font-size: 0.78125rem; }
|
||||
.ab-table thead th { background: #fafbfd; color: #1f2937; font-weight: 600; text-align: left; border-bottom: 1px solid #e6e9f0; padding: 0.5625rem 0.625rem; white-space: nowrap; }
|
||||
.ab-table thead th.ab-num { text-align: right; }
|
||||
.ab-table-grouped { min-width: 2200px; }
|
||||
.ab-table thead .ab-group th { background: #f0f3f9; color: #6b7280; font-size: 0.75rem; font-weight: 600; text-align: center; border-bottom: 1px solid #dfe4ec; padding: 0.625rem; white-space: nowrap; }
|
||||
.ab-table thead .ab-col th { background: #fafbfd; color: #1f2937; font-weight: 600; text-align: left; border-bottom: 1px solid #e6e9f0; padding: 0.5625rem 0.625rem; white-space: nowrap; }
|
||||
.ab-table thead .ab-col th.ab-num { text-align: right; }
|
||||
.ab-sort { color: #9aa3b2; margin-left: 0.1875rem; }
|
||||
.ab-table tbody td { padding: 0.5625rem 0.625rem; border-bottom: 1px solid #f1f3f7; white-space: nowrap; color: #1f2937; }
|
||||
.ab-table tbody tr:hover { background: #f7f9ff; }
|
||||
@ -309,6 +328,8 @@ export default {
|
||||
.ab-tag { display: inline-block; padding: 0.0625rem 0.5rem; border-radius: 1rem; font-size: 0.71875rem; font-weight: 500; background: #eef2ff; color: #4f46e5; }
|
||||
|
||||
.ab-empty { padding: 3rem; text-align: center; color: #9aa3b2; }
|
||||
.ab-error { color: #dc2626; }
|
||||
.ab-error .ab-btn { margin-top: 0.75rem; color: #1f2937; }
|
||||
|
||||
.ab-pager { display: flex; align-items: center; gap: 0.625rem; padding: 0.875rem 1rem; border-top: 1px solid #e6e9f0; flex-wrap: wrap; }
|
||||
.ab-page-info { color: #6b7280; font-size: 0.78125rem; }
|
||||
|
||||
4
resources/assets/js/views/business/pages.js
vendored
4
resources/assets/js/views/business/pages.js
vendored
@ -40,8 +40,8 @@ const alipayBase = companyId
|
||||
: '/ecommerce-finance/alipay-bills';
|
||||
|
||||
const accountBase = companyId
|
||||
? `/${companyId}/ecommerce-finance/account-bills`
|
||||
: '/ecommerce-finance/account-bills';
|
||||
? `/${companyId}/ecommerce-finance/account-bills/type/${encodeURIComponent(tab)}`
|
||||
: `/ecommerce-finance/account-bills/type/${encodeURIComponent(tab)}`;
|
||||
|
||||
function resolveComponent() {
|
||||
// 店铺收款账户账单 › 淘系支付宝账户(独立实现)
|
||||
|
||||
@ -100,7 +100,7 @@
|
||||
</div>
|
||||
|
||||
@if (($page['slug'] ?? null) === 'store-receiving-bills')
|
||||
<script src="{{ asset('js/business/pages.min.js') }}"></script>
|
||||
<script src="{{ asset('js/business/pages.min.js') }}?v={{ filemtime(public_path('js/business/pages.min.js')) }}"></script>
|
||||
@endif
|
||||
</x-slot>
|
||||
</x-layouts.admin>
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Modules\EcommerceFinance\Http\Controllers\AccountBills;
|
||||
|
||||
Route::get('ecommerce-finance/account-bills/type/{bill_type}', [AccountBills::class, 'index'])
|
||||
->name('ecommerce-finance.account-bills.index');
|
||||
Route::get('ecommerce-finance/account-bills/{bill}', [AccountBills::class, 'show'])
|
||||
->name('ecommerce-finance.account-bills.show');
|
||||
|
||||
/**
|
||||
* 'admin' middleware applied to all routes
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user