diff --git a/config/business_navigation.php b/config/business_navigation.php index 7aea3581..40fafedb 100644 --- a/config/business_navigation.php +++ b/config/business_navigation.php @@ -72,9 +72,9 @@ return [ ['slug' => 'taobao-wechat', 'title' => '淘系微信账户'], ['slug' => 'pinduoduo', 'title' => '拼多多账户'], ['slug' => 'jd-wallet', 'title' => '京东网银钱包账户'], + ['slug' => 'jd-transactions', 'title' => '京东流水'], ['slug' => 'douyin', 'title' => '抖音账户'], ['slug' => 'dewu', 'title' => '得物账户'], - ['slug' => 'vipshop', 'title' => '唯品会账户'], ], ], ['slug' => 'marketing-account-balance', 'title' => '店铺营销账户余额'], diff --git a/modules/EcommerceFinance/AccountBillColumns.php b/modules/EcommerceFinance/AccountBillColumns.php index db4eda34..9c4ef75d 100644 --- a/modules/EcommerceFinance/AccountBillColumns.php +++ b/modules/EcommerceFinance/AccountBillColumns.php @@ -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}> + * @return array,columns:array}> */ 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} + * @return array{title:string,groups:array,columns:array} */ 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, ]; } diff --git a/modules/EcommerceFinance/Database/Migrations/2026_07_21_000003_add_alipay_bill_detail_columns.php b/modules/EcommerceFinance/Database/Migrations/2026_07_21_000003_add_alipay_bill_detail_columns.php new file mode 100644 index 00000000..4f8157cd --- /dev/null +++ b/modules/EcommerceFinance/Database/Migrations/2026_07_21_000003_add_alipay_bill_detail_columns.php @@ -0,0 +1,24 @@ +string('finance_remark', 255)->nullable()->after('store_name'); + $table->string('order_no', 64)->nullable()->after('finance_remark'); + $table->decimal('amount', 20, 6)->nullable()->after('order_no'); + }); + } + + public function down(): void + { + Schema::table('ec_alipay_bills', function (Blueprint $table) { + $table->dropColumn(['finance_remark', 'order_no', 'amount']); + }); + } +}; diff --git a/modules/EcommerceFinance/Http/Controllers/AlipayBills.php b/modules/EcommerceFinance/Http/Controllers/AlipayBills.php index 9e7a484c..6cf2a5d8 100644 --- a/modules/EcommerceFinance/Http/Controllers/AlipayBills.php +++ b/modules/EcommerceFinance/Http/Controllers/AlipayBills.php @@ -35,6 +35,14 @@ class AlipayBills extends Controller $query->where('business_type', $type); } + if ($orderNo = $request->get('order_no')) { + $query->where('order_no', 'like', '%' . $orderNo . '%'); + } + + if ($financeRemark = $request->get('finance_remark')) { + $query->where('finance_remark', 'like', '%' . $financeRemark . '%'); + } + if ($start = $request->get('start')) { $query->where('occurred_at', '>=', $start); } @@ -48,10 +56,12 @@ class AlipayBills extends Controller $like = '%' . $keyword . '%'; $q->where('goods_name', 'like', $like) ->orWhere('record_code', 'like', $like) + ->orWhere('order_no', 'like', $like) ->orWhere('account_order_no', 'like', $like) ->orWhere('business_serial_no', 'like', $like) ->orWhere('merchant_order_no', 'like', $like) ->orWhere('online_order_no', 'like', $like) + ->orWhere('finance_remark', 'like', $like) ->orWhere('remark', 'like', $like); }); } diff --git a/modules/EcommerceFinance/Models/AlipayBill.php b/modules/EcommerceFinance/Models/AlipayBill.php index 3211c9a7..42f441e3 100644 --- a/modules/EcommerceFinance/Models/AlipayBill.php +++ b/modules/EcommerceFinance/Models/AlipayBill.php @@ -15,6 +15,9 @@ class AlipayBill extends Model 'company_id', 'record_code', 'store_name', + 'finance_remark', + 'order_no', + 'amount', 'custom_remark', 'bill_item', 'business_type', @@ -43,6 +46,7 @@ class AlipayBill extends Model protected $casts = [ 'occurred_at' => 'datetime', + 'amount' => 'decimal:6', 'income' => 'decimal:6', 'expense' => 'decimal:6', 'balance' => 'decimal:6', diff --git a/resources/assets/js/components/business/AccountBills.vue b/resources/assets/js/components/business/AccountBills.vue index db78097e..be73d5ec 100644 --- a/resources/assets/js/components/business/AccountBills.vue +++ b/resources/assets/js/components/business/AccountBills.vue @@ -54,15 +54,20 @@
-
{{ columnsTitle }}
+
{{ columnGroups.length ? '账单明细' : columnsTitle }}
{{ total }} 条
- +
- - + + + + + +
+ + {{ group.label }} +
{{ c.label }} ⇅ @@ -76,11 +81,18 @@
没有符合条件的账单记录
-
没有符合条件的账单记录
-
加载中…
+
加载中…
+
+
账单加载失败,请重试
+ +
+
暂无账单字段
@@ -118,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, @@ -147,6 +161,7 @@ export default { methods: { async fetch() { this.loading = true; + this.loadError = false; const params = { bill_type: this.billType, ...this.filters, @@ -168,12 +183,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; } @@ -295,8 +315,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; } @@ -307,6 +329,8 @@ export default { .ab-tag { display: inline-block; padding: 0.0625rem 0.5rem; border-radius: 1rem; font-size: 0.71875rem; font-weight: 500; background: var(--vip-content-accent-soft); color: var(--vip-content-accent-dark); } .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; } diff --git a/resources/assets/js/components/business/TaobaoAlipayBills.vue b/resources/assets/js/components/business/TaobaoAlipayBills.vue index 1de42e86..72ea15f0 100644 --- a/resources/assets/js/components/business/TaobaoAlipayBills.vue +++ b/resources/assets/js/components/business/TaobaoAlipayBills.vue @@ -82,39 +82,41 @@
- +
- - - - + + - + + + + + - - - - - - - - + + - + + + + + + + @@ -124,39 +126,42 @@ + + + - - - - - - - - + + - + + + + + + + + + +
标识与店铺账单与业务账号与流水商品基础信息账户与交易 金额(元)时间业务关联维护信息
记录编码 ⇅ 原始店铺财务备注订单号金额 自定义备注 账单项目业务类型业务描述备注 支付宝账号对方账号 账务订单号 业务流水号 商户订单号 业务基础订单号线上单号业务订单号业务账单来源 商品名称线上单号对应实际店铺对方账号发生时间 ⇅ 收入 ⇅ 支出 ⇅ 余额 ⇅发生时间 ⇅业务类型备注线上单号线上单号对应实际店铺业务描述业务账单来源业务订单号 创建时间 修改时间 修改人
{{ r.record_code }} {{ r.store_name }}{{ r.finance_remark || '—' }}{{ r.order_no || '—' }}{{ r.amount === null || r.amount === undefined ? '—' : money(r.amount) }} {{ r.custom_remark || '—' }} {{ r.bill_item }} - {{ r.business_type }} - {{ r.business_description || '—' }}{{ r.remark || '—' }} {{ r.alipay_account }}{{ r.counterparty_account }} {{ r.account_order_no }} {{ r.business_serial_no }} {{ r.merchant_order_no || '—' }} {{ r.business_base_order_no || '—' }}{{ r.online_order_no || '—' }}{{ r.business_order_no || '—' }}{{ r.business_bill_source || '—' }} {{ r.goods_name }}{{ r.online_real_store || '—' }}{{ r.counterparty_account || '—' }}{{ r.occurred_at || '—' }} +{{ money(r.income) }} — −{{ money(r.expense) }} — {{ money(r.balance) }}{{ r.occurred_at }}{{ r.business_type || '—' }}{{ r.remark || '—' }}{{ r.online_order_no || '—' }}{{ r.online_real_store || '—' }}{{ r.business_description || '—' }}{{ r.business_bill_source || '—' }}{{ r.business_order_no || '—' }} {{ r.created_at }} {{ r.updated_at }} {{ r.modifier || '—' }}
没有符合条件的账单记录
-
没有符合条件的账单记录
-
加载中…
+
加载中…
diff --git a/resources/assets/js/views/business/pages.js b/resources/assets/js/views/business/pages.js index aeba3302..402eb116 100644 --- a/resources/assets/js/views/business/pages.js +++ b/resources/assets/js/views/business/pages.js @@ -16,7 +16,7 @@ import TaobaoAlipayBills from './../../components/business/TaobaoAlipayBills.vue import AccountBills from './../../components/business/AccountBills.vue'; const GENERIC_TABS = ['taobao-wechat', 'pinduoduo', 'jd-wallet', 'jd-transactions', 'douyin', 'dewu']; -const STORE_RECEIVING_TABS = ['taobao-alipay', 'taobao-wechat', 'pinduoduo', 'jd-wallet', 'douyin', 'dewu', 'vipshop']; +const STORE_RECEIVING_TABS = ['taobao-alipay', 'taobao-wechat', 'pinduoduo', 'jd-wallet', 'jd-transactions', 'douyin', 'dewu']; function pageContext(pathname = window.location.pathname) { const parts = (pathname || '').split('/').filter(Boolean);