在京东账单右侧新增京喜账单页签,复用京东日账单的取数、列定义、筛选、排序、分页与导出,只增加平台维度过滤:京东账单排除京喜店铺,京喜账单只取京喜店铺。平台口径集中在 config/jd_bill_platform.php 与 JdBillPlatform(含口径切换起始日期参数,默认全量历史),仓库通过 forPlatform() 收窄,两个口径互补、总额守恒,底层镜像数据不修改不删除。真实镜像实测:京喜 488,464 笔 + 京东 210,983 笔 = 拆分前 699,447 笔,收入/支出/差额逐项误差为 0。
169 lines
6.3 KiB
JavaScript
Vendored
169 lines
6.3 KiB
JavaScript
Vendored
/**
|
||
* 业务工作台(账单流水数据 › 各子功能)统一前端入口。
|
||
* 对应 Blade:resources/views/business/pages/show.blade.php
|
||
* 路由:/{company_id}/workspace/{section}/{page}/{tab}
|
||
*
|
||
* 店铺收款账户账单(store-receiving-bills)下各 tab:
|
||
* - taobao-alipay → 独立实现 TaobaoAlipayBills(经营分析副本共享镜像)
|
||
* - taobao-wechat / pinduoduo / jd-wallet / jd-transactions / jingxi / dewu / vipshop / vipshop-jx
|
||
* → 通用实现 AccountBills(表 ec_account_bills,按 bill_type 区分)
|
||
* - douyin → AccountBills 展示共享原始账单镜像中的头条放心购渠道
|
||
*/
|
||
|
||
require('./../../bootstrap');
|
||
|
||
import Vue from 'vue';
|
||
import TaobaoAlipayBills from './../../components/business/TaobaoAlipayBills.vue';
|
||
import AccountBills from './../../components/business/AccountBills.vue';
|
||
|
||
const GENERIC_TABS = ['taobao-wechat', 'pinduoduo', 'jd-wallet', 'jd-transactions', 'jingxi', 'douyin', 'dewu', 'vipshop', 'vipshop-jx'];
|
||
const STORE_RECEIVING_TABS = ['taobao-alipay', 'taobao-wechat', 'pinduoduo', 'jd-wallet', 'jd-transactions', 'jingxi', 'douyin', 'dewu', 'vipshop', 'vipshop-jx'];
|
||
|
||
function pageContext(pathname = window.location.pathname) {
|
||
const parts = (pathname || '').split('/').filter(Boolean);
|
||
const idx = parts.indexOf('workspace');
|
||
|
||
if (idx === -1) {
|
||
return { companyId: '', section: '', page: '', tab: '' };
|
||
}
|
||
|
||
return {
|
||
companyId: idx > 0 ? parts[idx - 1] : '',
|
||
section: parts[idx + 1] || '',
|
||
page: parts[idx + 2] || '',
|
||
tab: parts[idx + 3] || '',
|
||
};
|
||
}
|
||
|
||
function resolveComponent(context) {
|
||
const alipayBase = context.companyId
|
||
? `/${context.companyId}/ecommerce-finance/alipay-bills`
|
||
: '/ecommerce-finance/alipay-bills';
|
||
const accountBase = context.companyId
|
||
? `/${context.companyId}/ecommerce-finance/account-bills/type/${encodeURIComponent(context.tab)}`
|
||
: `/ecommerce-finance/account-bills/type/${encodeURIComponent(context.tab)}`;
|
||
// 店铺收款账户账单 › 淘系支付宝账户(独立实现)
|
||
if (context.page === 'store-receiving-bills' && context.tab === 'taobao-alipay') {
|
||
const exportBase = context.companyId
|
||
? `/${context.companyId}/ecommerce-finance/alipay-bills/export`
|
||
: '/ecommerce-finance/alipay-bills/export';
|
||
return { Component: TaobaoAlipayBills, props: { apiBase: alipayBase, exportBase } };
|
||
}
|
||
|
||
// 店铺收款账户账单 › 其它账户类型(通用实现)
|
||
if (context.page === 'store-receiving-bills' && GENERIC_TABS.indexOf(context.tab) !== -1) {
|
||
return { Component: AccountBills, props: { apiBase: accountBase, billType: context.tab } };
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
const mount = document.querySelector('.business-blank-page');
|
||
|
||
if (mount) {
|
||
const initialContext = pageContext();
|
||
// Vue replaces the original mount node; keep the identity across local tab switches.
|
||
const preferencesUser = mount.dataset.tablePreferencesUser || 'anonymous';
|
||
const titleSuffix = document.title.includes(' - ') ? document.title.slice(document.title.lastIndexOf(' - ')) : '';
|
||
|
||
function isStoreReceivingContext(context) {
|
||
return context.page === 'store-receiving-bills'
|
||
&& STORE_RECEIVING_TABS.indexOf(context.tab) !== -1;
|
||
}
|
||
|
||
function updateActiveTab(tab) {
|
||
document.querySelectorAll('.business-tab-link').forEach((link) => {
|
||
const linkContext = pageContext(new URL(link.href, window.location.origin).pathname);
|
||
const isActive = linkContext.tab === tab;
|
||
|
||
link.classList.toggle('is-active', isActive);
|
||
|
||
if (isActive) {
|
||
link.setAttribute('aria-current', 'page');
|
||
} else {
|
||
link.removeAttribute('aria-current');
|
||
}
|
||
});
|
||
const label = document.querySelector('.business-tab-link[aria-current="page"] span:last-child')?.textContent.trim();
|
||
const title = document.querySelector('h1 [data-title-truncate]');
|
||
if (label && title) {
|
||
title.textContent = label;
|
||
document.title = label + titleSuffix;
|
||
}
|
||
}
|
||
|
||
/* eslint-disable no-new */
|
||
const workspace = new Vue({
|
||
el: mount,
|
||
data: {
|
||
context: initialContext,
|
||
},
|
||
|
||
render(h) {
|
||
const resolved = resolveComponent(this.context);
|
||
|
||
if (resolved) {
|
||
return h(resolved.Component, {
|
||
key: this.context.tab,
|
||
props: { ...resolved.props, userKey: preferencesUser },
|
||
});
|
||
}
|
||
|
||
return h('div', { class: 'business-page-empty' }, '该页面尚未实现');
|
||
},
|
||
});
|
||
|
||
function navigate(url, pushState = true) {
|
||
const target = new URL(url, window.location.origin);
|
||
const nextContext = pageContext(target.pathname);
|
||
|
||
if (target.origin !== window.location.origin || !isStoreReceivingContext(nextContext)) {
|
||
return false;
|
||
}
|
||
|
||
if (pushState && target.pathname !== window.location.pathname) {
|
||
window.history.pushState({}, '', `${target.pathname}${target.search}${target.hash}`);
|
||
}
|
||
|
||
workspace.context = nextContext;
|
||
updateActiveTab(nextContext.tab);
|
||
|
||
return true;
|
||
}
|
||
|
||
const tabBar = document.querySelector('.business-tab-bar');
|
||
|
||
if (tabBar) {
|
||
tabBar.addEventListener('click', (event) => {
|
||
const link = event.target.closest('.business-tab-link');
|
||
|
||
if (!link
|
||
|| event.button !== 0
|
||
|| event.metaKey
|
||
|| event.ctrlKey
|
||
|| event.shiftKey
|
||
|| event.altKey
|
||
) {
|
||
return;
|
||
}
|
||
|
||
const nextContext = pageContext(new URL(link.href, window.location.origin).pathname);
|
||
|
||
if (!isStoreReceivingContext(nextContext)) {
|
||
return;
|
||
}
|
||
|
||
// 在标签栏捕获阶段阻止原始链接和全局导航监听器,避免整页刷新。
|
||
event.preventDefault();
|
||
event.stopPropagation();
|
||
navigate(link.href);
|
||
}, true);
|
||
}
|
||
|
||
window.addEventListener('popstate', () => {
|
||
navigate(window.location.href, false);
|
||
});
|
||
|
||
updateActiveTab(initialContext.tab);
|
||
}
|