diff --git a/modules/EcommerceFinance/Database/Migrations/2026_07_21_000001_create_ec_alipay_bills_table.php b/modules/EcommerceFinance/Database/Migrations/2026_07_21_000001_create_ec_alipay_bills_table.php new file mode 100644 index 00000000..19f25c71 --- /dev/null +++ b/modules/EcommerceFinance/Database/Migrations/2026_07_21_000001_create_ec_alipay_bills_table.php @@ -0,0 +1,74 @@ +increments('id'); + $table->unsignedInteger('company_id'); + + // —— 标识与店铺 —— + $table->string('record_code', 64); // 记录编码 + $table->string('store_name', 255); // 原始店铺 + $table->string('custom_remark', 255)->nullable(); // 自定义备注 + + // —— 账单与业务 —— + $table->string('bill_item', 64); // 账单项目 + $table->string('business_type', 32); // 业务类型 + $table->string('business_description', 512)->nullable(); // 业务描述 + $table->string('remark', 512)->nullable(); // 备注 + + // —— 账号与流水 —— + $table->string('alipay_account', 64); // 支付宝账号 + $table->string('counterparty_account', 255); // 对方账号 + $table->string('account_order_no', 64); // 账务订单号 + $table->string('business_serial_no', 64); // 业务流水号 + $table->string('merchant_order_no', 64)->nullable(); // 商户订单号 + $table->string('business_base_order_no', 64)->nullable(); // 业务基础订单号 + $table->string('online_order_no', 64)->nullable(); // 线上单号 + $table->string('business_order_no', 64)->nullable(); // 业务订单号 + $table->string('business_bill_source', 128)->nullable(); // 业务账单来源 + + // —— 商品 —— + $table->string('goods_name', 255); // 商品名称 + $table->string('online_real_store', 255)->nullable(); // 线上单号对应实际店铺 + + // —— 金额(元) —— + $table->decimal('income', 20, 6)->default(0); // 收入 + $table->decimal('expense', 20, 6)->default(0); // 支出 + $table->decimal('balance', 20, 6)->default(0); // 余额 + + // —— 时间 —— + $table->dateTime('occurred_at')->nullable(); // 发生时间 + + $table->string('modifier', 64)->nullable(); // 修改人 + $table->string('platform', 32)->default('taobao'); // 平台(淘系/京东...),预留 + + $table->unsignedInteger('created_by')->nullable(); + $table->string('created_from', 100)->nullable(); + $table->timestamps(); + $table->softDeletes(); + + $table->unique(['company_id', 'record_code', 'deleted_at']); + $table->index(['company_id', 'store_name']); + $table->index(['company_id', 'alipay_account']); + $table->index(['company_id', 'bill_item']); + $table->index(['company_id', 'business_type']); + $table->index(['company_id', 'occurred_at']); + }); + } + + public function down(): void + { + Schema::dropIfExists('ec_alipay_bills'); + } +}; diff --git a/modules/EcommerceFinance/Database/Seeds/AlipayBillsTableSeeder.php b/modules/EcommerceFinance/Database/Seeds/AlipayBillsTableSeeder.php new file mode 100644 index 00000000..d359c658 --- /dev/null +++ b/modules/EcommerceFinance/Database/Seeds/AlipayBillsTableSeeder.php @@ -0,0 +1,134 @@ +value('id') ?? 1); + + DB::table('ec_alipay_bills')->where('company_id', $companyId)->delete(); + + $rows = [ + // —— 表1 真实样例 —— + [ + 'record_code' => '2000000001114707218', + 'store_name' => '淘宝-亿家达家居鞋柜电脑桌', + 'bill_item' => '交易收款', 'business_type' => '交易付款', + 'remark' => '实木腿窄书桌书架一体电脑桌床边桌卧室家用小户型学习桌写字桌子', + 'alipay_account' => '2088680870590483', 'counterparty_account' => '**文', + 'account_order_no' => '1570801495986359201', + 'business_serial_no' => '2026062923001159201451054134', + 'merchant_order_no' => 'T200P5121711939135003306', + 'online_order_no' => '5121711939135003306', + 'goods_name' => '实木腿窄书桌书架一体电脑桌床边桌卧室家用小户型学习桌写字桌子', + 'online_real_store' => '淘宝-亿家达家居鞋柜电脑桌', + 'income' => 130.93, 'expense' => 0.00, 'balance' => 13899.81, + 'occurred_at' => '2026-07-01 23:57:11', 'modifier' => 'api', + ], + [ + 'record_code' => '2000000001114782775', + 'store_name' => '天猫-亿家达旗舰店', + 'bill_item' => '以旧换新自补平台过桥', 'business_type' => '交易分账', + 'remark' => '以旧换新自补平台过桥{3310629457741000253}', + 'alipay_account' => '2088870779873392', 'counterparty_account' => '浙江天猫技术有限公司', + 'account_order_no' => '1570778496992153730', + 'business_serial_no' => '2026062823001153731421787379', + 'merchant_order_no' => 'T200P3310629457741000253', + 'online_order_no' => '3310629457741000253', + 'goods_name' => '书柜储物柜一体靠墙置物柜客厅墙边小格子柜卧室床边柜子飘窗书架', + 'online_real_store' => '天猫-亿家达旗舰店', + 'income' => 0.00, 'expense' => 17.44, 'balance' => 253157.10, + 'occurred_at' => '2026-07-01 23:55:56', 'modifier' => 'api', + ], + [ + 'record_code' => '2000000001114787788', + 'store_name' => '天猫-卓禾家具旗舰店', + 'bill_item' => '以旧换新自补平台过桥', 'business_type' => '交易分账', + 'remark' => '以旧换新自补平台过桥{3310023615943000698}', + 'alipay_account' => '2088480341979438', 'counterparty_account' => '浙江天猫技术有限公司', + 'account_order_no' => '1570765667613157810', + 'business_serial_no' => '2026062623001157811400561188', + 'merchant_order_no' => 'T200P3310023615943000698', + 'online_order_no' => '3310023615943000698', + 'goods_name' => '沙发边几可移动升降小茶几桌子中古风客厅C型床边桌电脑桌置物架', + 'online_real_store' => '天猫-卓禾家具旗舰店', + 'income' => 0.00, 'expense' => 32.35, 'balance' => 83929.40, + 'occurred_at' => '2026-07-01 23:55:52', 'modifier' => 'api', + ], + ]; + + // —— 补充演示行(覆盖更多 账单项目 / 业务类型) —— + $shops = ['淘宝-亿家达家居鞋柜电脑桌', '天猫-亿家达旗舰店', '天猫-卓禾家具旗舰店']; + $items = [ + ['交易收款', '交易付款', 0], + ['退款', '退款', 1], + ['提现到银行卡', '提现', 1], + ['服务费', '手续费', 1], + ['红包补贴', '交易分账', 0], + ['以旧换新自补平台过桥', '交易分账', 1], + ]; + $goods = [ + '北欧实木餐桌椅组合小户型吃饭桌', + '懒人沙发卧室阳台休闲单椅', + '岩板茶几客厅现代简约小茶桌', + '儿童学习桌可升降书桌写字台', + '衣柜简易组装卧室衣橱', + '实木床头柜卧室收纳柜', + ]; + + $seq = 2000000001114790000; + $balance = 90000.00; + for ($i = 0; $i < 14; $i++) { + [$item, $type, $isOut] = $items[$i % count($items)]; + $shop = $shops[$i % count($shops)]; + $amount = $isOut + ? round(5 + ($i * 13 % 120), 2) + : round(80 + ($i * 37 % 900), 2); + $balance += $isOut ? -$amount : $amount; + $day = str_pad((string) (1 + ($i % 15)), 2, '0', STR_PAD_LEFT); + $hh = str_pad((string) (8 + ($i % 12)), 2, '0', STR_PAD_LEFT); + $mm = str_pad((string) (($i * 7) % 60), 2, '0', STR_PAD_LEFT); + + $rows[] = [ + 'record_code' => (string) ($seq++), + 'store_name' => $shop, + 'bill_item' => $item, 'business_type' => $type, + 'remark' => $item === '以旧换新自补平台过桥' ? ('以旧换新自补平台过桥{33' . (1000000000000000 + $i) . '}') : $item, + 'alipay_account' => '2088' . (800000000000 + $i), + 'counterparty_account' => $isOut ? '浙江天猫技术有限公司' : '**客', + 'account_order_no' => (string) (1570700000000000000 + $i), + 'business_serial_no' => '202606' . $day . '2300115' . (1000000 + $i), + 'merchant_order_no' => 'T200P' . (3300000000000000 + $i), + 'online_order_no' => (string) (3300000000000000 + $i), + 'goods_name' => $goods[$i % count($goods)], + 'online_real_store' => $shop, + 'income' => $isOut ? 0.00 : $amount, + 'expense' => $isOut ? $amount : 0.00, + 'balance' => round($balance, 2), + 'occurred_at' => '2026-07-' . $day . ' ' . $hh . ':' . $mm . ':11', + 'modifier' => 'api', + ]; + } + + $now = now(); + foreach ($rows as &$row) { + $row['company_id'] = $companyId; + $row['platform'] = 'taobao'; + $row['created_from'] = 'ecommerce-finance'; + $row['created_at'] = $now; + $row['updated_at'] = $now; + } + unset($row); + + DB::table('ec_alipay_bills')->insert($rows); + } +} diff --git a/modules/EcommerceFinance/Http/Controllers/AlipayBills.php b/modules/EcommerceFinance/Http/Controllers/AlipayBills.php new file mode 100644 index 00000000..ab7da6b4 --- /dev/null +++ b/modules/EcommerceFinance/Http/Controllers/AlipayBills.php @@ -0,0 +1,91 @@ +where('company_id', company_id()); + + if ($store = $request->get('store_name')) { + $query->where('store_name', $store); + } + + if ($alipay = $request->get('alipay_account')) { + $query->where('alipay_account', 'like', '%' . $alipay . '%'); + } + + if ($item = $request->get('bill_item')) { + $query->where('bill_item', $item); + } + + if ($type = $request->get('business_type')) { + $query->where('business_type', $type); + } + + if ($start = $request->get('start')) { + $query->where('occurred_at', '>=', $start); + } + + if ($end = $request->get('end')) { + $query->where('occurred_at', '<=', $end . ' 23:59:59'); + } + + if ($keyword = $request->get('keyword')) { + $query->where(function ($q) use ($keyword) { + $like = '%' . $keyword . '%'; + $q->where('goods_name', 'like', $like) + ->orWhere('record_code', '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('remark', 'like', $like); + }); + } + + $sortable = ['occurred_at', 'income', 'expense', 'balance', 'record_code']; + $sort = in_array($request->get('sort'), $sortable, true) ? $request->get('sort') : 'occurred_at'; + $dir = $request->get('dir') === 'asc' ? 'asc' : 'desc'; + $query->orderBy($sort, $dir); + + $perPage = min(max((int) $request->get('limit', 10), 1), 100); + $rows = $query->paginate($perPage); + + // 汇总:基于当前筛选结果(分页前) + $summaryRow = (clone $query)->selectRaw( + 'COALESCE(SUM(income), 0) as income, ' . + 'COALESCE(SUM(expense), 0) as expense, ' . + 'COUNT(*) as count' + )->first(); + + $latestBalance = (clone $query) + ->orderByDesc('occurred_at') + ->orderByDesc('id') + ->value('balance'); + + $data = $rows->toArray(); + $data['summary'] = [ + 'income' => (float) ($summaryRow->income ?? 0), + 'expense' => (float) ($summaryRow->expense ?? 0), + 'count' => (int) ($summaryRow->count ?? 0), + 'balance' => $latestBalance !== null ? (float) $latestBalance : 0, + ]; + + return response()->json($data); + } + + public function show(AlipayBill $bill) + { + return response()->json($bill); + } +} diff --git a/modules/EcommerceFinance/Models/AlipayBill.php b/modules/EcommerceFinance/Models/AlipayBill.php new file mode 100644 index 00000000..3211c9a7 --- /dev/null +++ b/modules/EcommerceFinance/Models/AlipayBill.php @@ -0,0 +1,50 @@ + 'datetime', + 'income' => 'decimal:6', + 'expense' => 'decimal:6', + 'balance' => 'decimal:6', + ]; +} diff --git a/modules/EcommerceFinance/Routes/admin.php b/modules/EcommerceFinance/Routes/admin.php index 5a08c09f..5b38223f 100644 --- a/modules/EcommerceFinance/Routes/admin.php +++ b/modules/EcommerceFinance/Routes/admin.php @@ -4,4 +4,8 @@ use Illuminate\Support\Facades\Route; Route::admin('ecommerce-finance', function () { Route::view('/', 'ecommerce-finance::index')->name('index'); + + // 店铺收款账户账单 › 淘系支付宝账户 + Route::get('alipay-bills', 'AlipayBills@index')->name('alipay-bills.index'); + Route::get('alipay-bills/{bill}', 'AlipayBills@show')->name('alipay-bills.show'); }); diff --git a/resources/assets/js/components/business/TaobaoAlipayBills.vue b/resources/assets/js/components/business/TaobaoAlipayBills.vue new file mode 100644 index 00000000..f98531c8 --- /dev/null +++ b/resources/assets/js/components/business/TaobaoAlipayBills.vue @@ -0,0 +1,473 @@ + + + + + diff --git a/resources/assets/js/views/business/pages.js b/resources/assets/js/views/business/pages.js new file mode 100644 index 00000000..fa6348bf --- /dev/null +++ b/resources/assets/js/views/business/pages.js @@ -0,0 +1,51 @@ +/** + * 业务工作台(店铺管理 › 各子功能)统一前端入口。 + * 对应 Blade:resources/views/business/pages/show.blade.php + * 从当前 URL(/{company_id}/workspace/{section}/{page}/{tab})取出 + * company_id 与 page slug,挂载 Vue 并按 slug 渲染对应组件。 + * + * 淘系支付宝账户(store-receiving-bill › taobao-alipay)在此实现; + * 京东流水(jd-transactions)等后续页面复用同一框架,按 slug 增加分支即可。 + */ + +require('./../../bootstrap'); + +import Vue from 'vue'; +import TaobaoAlipayBills from './../../components/business/TaobaoAlipayBills.vue'; + +function pageContext() { + const parts = (window.location.pathname || '').split('/').filter(Boolean); + const idx = parts.indexOf('workspace'); + + if (idx === -1) { + return { companyId: '', page: '' }; + } + + const companyId = idx > 0 ? parts[idx - 1] : ''; + const page = parts[idx + 1] || ''; + + return { companyId, page }; +} + +const { companyId, page } = pageContext(); + +const apiBase = companyId + ? `/${companyId}/ecommerce-finance/alipay-bills` + : '/ecommerce-finance/alipay-bills'; + +const mount = document.querySelector('.business-blank-page'); + +if (mount) { + /* eslint-disable no-new */ + new Vue({ + el: mount, + + render(h) { + if (page === 'taobao-alipay') { + return h(TaobaoAlipayBills, { props: { apiBase } }); + } + + return h('div', { class: 'business-page-empty' }, '该页面尚未实现'); + }, + }); +} diff --git a/resources/views/business/pages/show.blade.php b/resources/views/business/pages/show.blade.php index 356de8f2..32822d6f 100644 --- a/resources/views/business/pages/show.blade.php +++ b/resources/views/business/pages/show.blade.php @@ -98,5 +98,9 @@
+ + @if (in_array($page['slug'] ?? null, ['taobao-alipay', 'taobao-wechat', 'jd-wallet', 'jd-transactions'])) + + @endif diff --git a/webpack.mix.js b/webpack.mix.js index dbba92a9..413a418a 100644 --- a/webpack.mix.js +++ b/webpack.mix.js @@ -61,6 +61,9 @@ mix // Modules .js('resources/assets/js/views/modules/apps.js', 'public/js/modules/apps.min.js') + // Business workspace(店铺管理 › 各子功能) + .js('resources/assets/js/views/business/pages.js', 'public/js/business/pages.min.js') + // Portal .js('resources/assets/js/views/portal/apps.js', 'public/js/portal/apps.min.js')