refactor(admin-ui): 成本中心导航收敛为 4 个固定 Tab
原结构是「4 个来源 Tab(内容只有一句提示语)× 6 个内容 Tab」, 且来源 Tab 会增删内容 Tab:选「自动发货」后标准商品/渠道映射/发单价格直接消失, 切换来源还会强制跳转。用户反馈「逻辑不顺、很多 tab 没必要」。 - 来源改为工具栏 Segmented:只筛数据,不改变导航;Tab 永远 4 个 标准商品 / 渠道映射 / 成本配置 / 成本异常; - 自动发货 SKU、发单价格、人工 SKU 配置合并为「成本配置」, 选「全部」时给三个入口卡片,选具体来源时直接渲染对应面板; - 自动发货 SKU 原本是标准商品的同数据子集(同一个接口 + carrierType), 合并后不再有重复入口; - 渠道映射在自动发货/人工来源下改为说明性提示,不再展示空表; - 异常徽标改用当前来源的计数,不再出现「徽标 10 万、列表几百条」; - refreshAll 改为按 queryKey 前缀失效,修好漏刷 (诊断、未归一队列、人工 SKU 等 5 个查询); - 删除 Context 里 12 个从未被读取的字段(products/versions/exceptions 等 空数组与 loading 常量),注释改为与实现一致; - 「生效发单价格」改名「生效成本版本」——它统计的是全部 active 版本, 按来源过滤后叫发单价格会误导。 验证:后端 786 测试、前端 lint/typecheck/test/build 通过。
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
/**
|
||||
* 成本中心页面入口。
|
||||
*
|
||||
* 实现已拆分到 `pages/admin/cost-center/` 下的各 Panel:
|
||||
* - CostCenterShell.tsx 页面骨架、顶部来源切换、Tab 定义
|
||||
* 页面结构(2026-10-25 收敛为 4 个固定 Tab):
|
||||
* - CostCenterShell.tsx 页面骨架:来源筛选(Segmented)、统计卡、4 个 Tab
|
||||
* - ProductCatalogPanel.tsx 标准商品
|
||||
* - ChannelMappingPanel.tsx 渠道映射
|
||||
* - AffiliateSkuPanel.tsx 自动发货 SKU
|
||||
* - ManualSkuConfigPanel.tsx 人工 SKU 配置(消耗积分即人工成本)
|
||||
* - WorkOrderPricePanel.tsx 发单价格(只读核对接单模板发单金额)
|
||||
* - ChannelMappingPanel.tsx 渠道映射(映射目录 + 未归一队列)
|
||||
* - CostConfigPanel.tsx 成本配置:按来源切换
|
||||
* ├ AffiliateSkuPanel 自动发货采购价
|
||||
* ├ WorkOrderPricePanel 接单平台发单金额(只读)
|
||||
* └ ManualSkuConfigPanel 人工客服 SKU 消耗
|
||||
* - CostExceptionPanel.tsx 成本异常(按原因聚合 + 近 24 小时默认)
|
||||
* - CostPreviewModal.tsx 成本解析弹窗(异常行 / 订单详情进入)
|
||||
*/
|
||||
|
||||
@@ -1,41 +1,27 @@
|
||||
/**
|
||||
* 成本中心页面上下文。
|
||||
*
|
||||
* 面板只读这里的查询结果与动作,不自己发请求,避免同一页多套口径。
|
||||
* 只存放「所有面板都要知道」的三件事:权限、当前来源筛选、刷新动作。
|
||||
* 具体数据由各面板自己用 react-query 取——曾经这里塞过 products / versions /
|
||||
* exceptions 等空数组当作「统一数据源」,实际没人读,已删除。
|
||||
*/
|
||||
import { createContext, useContext } from 'react'
|
||||
|
||||
import type {
|
||||
ChannelProductMapping,
|
||||
CostException,
|
||||
CostItem,
|
||||
CostModel,
|
||||
CostPreview,
|
||||
CostVersion,
|
||||
ProductCatalogItem,
|
||||
ProductSource,
|
||||
} from '@/types/admin'
|
||||
import type { CostItem, CostModel, CostPreview, ProductSource } from '@/types/admin'
|
||||
|
||||
import type { CostScope } from './shared'
|
||||
|
||||
export type CostCenterContextValue = {
|
||||
canConfig: boolean
|
||||
/** 当前来源筛选:all / affiliate_dash / work_order / manual。 */
|
||||
scope: CostScope
|
||||
setScope: (scope: CostScope) => void
|
||||
scopeLabel: string
|
||||
/** 商品/映射按来源前缀筛选;成本项/版本/异常按履约方式筛选。 */
|
||||
/** 商品/映射按 canonical_sku 前缀筛选。 */
|
||||
productSourceFilter?: ProductSource
|
||||
/** 成本项/版本/异常按履约方式筛选。 */
|
||||
fulfillmentModeFilter?: 'affiliate_dash' | 'work_order' | 'manual'
|
||||
|
||||
overview?: {
|
||||
productCount: number
|
||||
mappingCount: number
|
||||
costItemCount: number
|
||||
activeVersionCount: number
|
||||
openExceptionCount: number
|
||||
unmappedOrderItemCount: number
|
||||
productSourceCounts?: Record<string, number>
|
||||
costModelCounts?: Record<string, number>
|
||||
}
|
||||
options?: {
|
||||
providers: string[]
|
||||
products: Array<{
|
||||
@@ -61,26 +47,7 @@ export type CostCenterContextValue = {
|
||||
}>
|
||||
}
|
||||
|
||||
products: ProductCatalogItem[]
|
||||
mappingGroups: Array<{
|
||||
canonicalProductId: number
|
||||
canonicalSku: string
|
||||
canonicalName: string
|
||||
category: string
|
||||
unitName: string
|
||||
status: 'active' | 'archived'
|
||||
mappings: ChannelProductMapping[]
|
||||
}>
|
||||
costItems: CostItem[]
|
||||
versions: CostVersion[]
|
||||
exceptions: CostException[]
|
||||
|
||||
productsLoading: boolean
|
||||
mappingsLoading: boolean
|
||||
costItemsLoading: boolean
|
||||
versionsLoading: boolean
|
||||
exceptionsLoading: boolean
|
||||
|
||||
/** 全量刷新:按 queryKey 前缀失效,避免漏刷新增的查询。 */
|
||||
refreshAll: () => void
|
||||
}
|
||||
|
||||
|
||||
@@ -1,34 +1,43 @@
|
||||
/**
|
||||
* 成本中心外壳:顶部来源切换、总览统计与 Tab 定义。
|
||||
* 成本中心外壳:来源筛选、总览统计与固定 Tab。
|
||||
*
|
||||
* 各 Tab 由独立 Panel 组件承载,自己取数、自己维护表单与弹窗,
|
||||
* 避免单文件堆积成不可维护的巨型页面。
|
||||
* 结构(2026-10-25 调整):
|
||||
* 1. 来源不再是「假 Tab」,改为工具栏 Segmented —— 只筛数据,不改变导航;
|
||||
* 2. Tab 固定 4 个,不再随来源增减:标准商品 / 渠道映射 / 成本配置 / 成本异常;
|
||||
* 3. 原来分散的「自动发货 SKU / 人工 SKU 配置 / 发单价格」合并为「成本配置」;
|
||||
* 4. 统计卡按当前来源收敛(overview 接口传 scope),和下面的列表对得上;
|
||||
* 5. 刷新按 queryKey 前缀失效,新增查询不会再漏刷。
|
||||
*/
|
||||
import { ReloadOutlined } from '@ant-design/icons'
|
||||
import { Alert, Button, Card, Col, Row, Statistic, Tabs, Tag, Typography } from 'antd'
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
Card,
|
||||
Col,
|
||||
Row,
|
||||
Segmented,
|
||||
Space,
|
||||
Statistic,
|
||||
Tabs,
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
import PageHeader from '@/components/admin/PageHeader'
|
||||
import { usePersistedState } from '@/hooks/usePersistedState'
|
||||
import { fetchAdminCostCenterOptions, fetchAdminCostCenterOverview } from '@/services/admin'
|
||||
import { hasAdminPermission } from '@/utils/admin-auth'
|
||||
|
||||
import { AffiliateSkuPanel } from './AffiliateSkuPanel'
|
||||
import { ChannelMappingPanel } from './ChannelMappingPanel'
|
||||
import CostConfigPanel from './CostConfigPanel'
|
||||
import { CostExceptionPanel } from './CostExceptionPanel'
|
||||
import { ManualSkuConfigPanel } from './ManualSkuConfigPanel'
|
||||
import { ProductCatalogPanel } from './ProductCatalogPanel'
|
||||
import { WorkOrderPricePanel } from './WorkOrderPricePanel'
|
||||
import { CostCenterContext } from './CostCenterContext'
|
||||
import type { CostScope } from './shared'
|
||||
|
||||
const SCOPES: Array<{ key: CostScope; label: string; hint: string }> = [
|
||||
{
|
||||
key: 'all',
|
||||
label: '全部',
|
||||
hint: '不区分来源,查看全部商品、映射、成本项与版本。',
|
||||
},
|
||||
{ key: 'all', label: '全部', hint: '不区分来源,查看全部商品、映射与成本。' },
|
||||
{
|
||||
key: 'affiliate_dash',
|
||||
label: '自动发货',
|
||||
@@ -37,30 +46,24 @@ const SCOPES: Array<{ key: CostScope; label: string; hint: string }> = [
|
||||
{
|
||||
key: 'work_order',
|
||||
label: '接单平台',
|
||||
hint: '需要打手接单履约的商品;成本以打手报酬为主,可按接单规则或商品配价。',
|
||||
hint: '需要打手接单履约的商品;成本以打手报酬为主,按接单模板配价。',
|
||||
},
|
||||
{
|
||||
key: 'manual',
|
||||
label: '人工客服',
|
||||
hint: '客服手工处理的商品;成本按人工实际支出逐单登记。',
|
||||
hint: '客服手工处理的商品;成本按内部 SKU 的消耗积分结算。',
|
||||
},
|
||||
]
|
||||
|
||||
const SCOPE_TAG_COLORS: Record<CostScope, string> = {
|
||||
all: 'default',
|
||||
affiliate_dash: 'green',
|
||||
work_order: 'blue',
|
||||
manual: 'orange',
|
||||
const TABS = ['products', 'mappings', 'cost', 'exceptions'] as const
|
||||
type CostCenterTab = (typeof TABS)[number]
|
||||
|
||||
function isCostCenterTab(value: unknown): value is CostCenterTab {
|
||||
return typeof value === 'string' && (TABS as readonly string[]).includes(value)
|
||||
}
|
||||
|
||||
function tabKeysForScope(scope: CostScope) {
|
||||
return [
|
||||
...(scope === 'all' || scope === 'work_order' ? ['products', 'mappings'] : []),
|
||||
...(scope === 'all' || scope === 'affiliate_dash' ? ['affiliate-skus'] : []),
|
||||
...(scope === 'all' || scope === 'manual' ? ['manual-skus'] : []),
|
||||
...(scope === 'all' || scope === 'work_order' ? ['prices'] : []),
|
||||
'exceptions',
|
||||
]
|
||||
function isCostScope(value: unknown): value is CostScope {
|
||||
return SCOPES.some((item) => item.key === value)
|
||||
}
|
||||
|
||||
export default function CostCenterShell() {
|
||||
@@ -70,13 +73,17 @@ export default function CostCenterShell() {
|
||||
const [scope, setScope] = usePersistedState<CostScope>(
|
||||
'admin-cost-center:scope',
|
||||
'all',
|
||||
(value): value is CostScope => SCOPES.some((item) => item.key === value),
|
||||
isCostScope,
|
||||
)
|
||||
const [activeTab, setActiveTab] = usePersistedState<CostCenterTab>(
|
||||
'admin-cost-center:tab',
|
||||
'products',
|
||||
isCostCenterTab,
|
||||
)
|
||||
const [activeTab, setActiveTab] = usePersistedState<string>('admin-cost-center:tab', 'products')
|
||||
|
||||
const overviewQuery = useQuery({
|
||||
queryKey: ['admin-cost-center-overview'],
|
||||
queryFn: fetchAdminCostCenterOverview,
|
||||
queryKey: ['admin-cost-center-overview', scope],
|
||||
queryFn: () => fetchAdminCostCenterOverview({ scope }),
|
||||
})
|
||||
const optionsQuery = useQuery({
|
||||
queryKey: ['admin-cost-center-options'],
|
||||
@@ -85,50 +92,31 @@ export default function CostCenterShell() {
|
||||
|
||||
const overview = overviewQuery.data?.data
|
||||
const options = optionsQuery.data?.data
|
||||
const visibleTabKeys = tabKeysForScope(scope)
|
||||
|
||||
useEffect(() => {
|
||||
if (!visibleTabKeys.includes(activeTab)) {
|
||||
setActiveTab(visibleTabKeys[0] ?? 'exceptions')
|
||||
}
|
||||
}, [activeTab, setActiveTab, visibleTabKeys])
|
||||
|
||||
function refreshAll() {
|
||||
void queryClient.invalidateQueries({ queryKey: ['admin-cost-center-overview'] })
|
||||
void queryClient.invalidateQueries({ queryKey: ['admin-cost-center-options'] })
|
||||
void queryClient.invalidateQueries({ queryKey: ['admin-cost-center-products'] })
|
||||
void queryClient.invalidateQueries({ queryKey: ['admin-cost-center-mappings'] })
|
||||
void queryClient.invalidateQueries({ queryKey: ['admin-cost-center-cost-versions'] })
|
||||
void queryClient.invalidateQueries({ queryKey: ['admin-cost-center-exceptions'] })
|
||||
void queryClient.invalidateQueries({ queryKey: ['admin-cost-center-exceptions-summary'] })
|
||||
// 按前缀失效:新增一个 admin-cost-center-* 查询不需要再回来改这里。
|
||||
void queryClient.invalidateQueries({
|
||||
predicate: (query) => String(query.queryKey[0] ?? '').startsWith('admin-cost-center'),
|
||||
})
|
||||
}
|
||||
|
||||
const scopeLabel =
|
||||
scope === 'all' ? '全部' : (SCOPES.find((item) => item.key === scope)?.label ?? '')
|
||||
const scopeLabel = SCOPES.find((item) => item.key === scope)?.label ?? '全部'
|
||||
const scopeHint = SCOPES.find((item) => item.key === scope)?.hint ?? ''
|
||||
const productSourceFilter = scope === 'all' ? undefined : scope
|
||||
const fulfillmentModeFilter =
|
||||
scope === 'all' ? undefined : (scope as 'affiliate_dash' | 'work_order' | 'manual')
|
||||
const mappingsApplicable = scope === 'all' || scope === 'work_order'
|
||||
|
||||
return (
|
||||
<CostCenterContext.Provider
|
||||
value={{
|
||||
canConfig,
|
||||
scope,
|
||||
setScope,
|
||||
scopeLabel,
|
||||
productSourceFilter,
|
||||
fulfillmentModeFilter,
|
||||
overview,
|
||||
options,
|
||||
products: [],
|
||||
mappingGroups: [],
|
||||
costItems: [],
|
||||
versions: [],
|
||||
exceptions: [],
|
||||
productsLoading: false,
|
||||
mappingsLoading: false,
|
||||
costItemsLoading: false,
|
||||
versionsLoading: false,
|
||||
exceptionsLoading: false,
|
||||
refreshAll,
|
||||
}}
|
||||
>
|
||||
@@ -147,12 +135,20 @@ export default function CostCenterShell() {
|
||||
}
|
||||
/>
|
||||
|
||||
<Space size={6}>
|
||||
<Typography.Text type="secondary">统计口径</Typography.Text>
|
||||
<Tag color={scope === 'all' ? 'default' : 'blue'}>{scopeLabel}</Tag>
|
||||
{scope !== 'all' ? (
|
||||
<Typography.Text type="secondary">(跟随上方来源筛选变化)</Typography.Text>
|
||||
) : null}
|
||||
</Space>
|
||||
|
||||
<Row gutter={[16, 16]}>
|
||||
{[
|
||||
['标准商品', overview?.productCount || 0],
|
||||
['渠道映射', overview?.mappingCount || 0],
|
||||
['系统成本项', overview?.costItemCount || 0],
|
||||
['生效发单价格', overview?.activeVersionCount || 0],
|
||||
['生效成本版本', overview?.activeVersionCount || 0],
|
||||
['待处理异常', overview?.openExceptionCount || 0],
|
||||
['未映射订单项', overview?.unmappedOrderItemCount || 0],
|
||||
].map(([label, value]) => (
|
||||
@@ -164,37 +160,29 @@ export default function CostCenterShell() {
|
||||
))}
|
||||
</Row>
|
||||
|
||||
<Card className="cost-center-carrier-card">
|
||||
<Tabs
|
||||
activeKey={scope}
|
||||
onChange={(key) => {
|
||||
const next = key as CostScope
|
||||
setScope(next)
|
||||
setActiveTab(
|
||||
next === 'all' || next === 'work_order'
|
||||
? 'products'
|
||||
: next === 'affiliate_dash'
|
||||
? 'affiliate-skus'
|
||||
: 'manual-skus',
|
||||
)
|
||||
}}
|
||||
items={SCOPES.map((item) => {
|
||||
const productCount =
|
||||
item.key === 'all'
|
||||
? overview?.productCount
|
||||
: overview?.productSourceCounts?.[item.key]
|
||||
return {
|
||||
key: item.key,
|
||||
<Card>
|
||||
<Space wrap size={12} align="center">
|
||||
<Segmented
|
||||
value={scope}
|
||||
onChange={(value) => setScope(value as CostScope)}
|
||||
options={SCOPES.map((item) => ({
|
||||
value: item.key,
|
||||
label: (
|
||||
<span className="cost-center-scope-tab">
|
||||
<Space size={4}>
|
||||
<span>{item.label}</span>
|
||||
<Tag color={SCOPE_TAG_COLORS[item.key]}>{Number(productCount || 0)} 商品</Tag>
|
||||
</span>
|
||||
<Tag>
|
||||
{Number(
|
||||
item.key === 'all'
|
||||
? (overview?.productTotalCount ?? overview?.productCount ?? 0)
|
||||
: (overview?.productSourceCounts?.[item.key] ?? 0),
|
||||
)}
|
||||
</Tag>
|
||||
</Space>
|
||||
),
|
||||
children: <Typography.Text type="secondary">{item.hint}</Typography.Text>,
|
||||
}
|
||||
})}
|
||||
/>
|
||||
}))}
|
||||
/>
|
||||
<Typography.Text type="secondary">{scopeHint}</Typography.Text>
|
||||
</Space>
|
||||
</Card>
|
||||
|
||||
{!canConfig ? (
|
||||
@@ -202,13 +190,13 @@ export default function CostCenterShell() {
|
||||
type="info"
|
||||
showIcon
|
||||
message="当前账号为只读权限"
|
||||
description="可以查看商品、映射、发单价格和成本异常;新增/修改需要 finance.config 权限。"
|
||||
description="可以查看商品、映射、成本配置和成本异常;新增/修改需要 finance.config 权限。"
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<Tabs
|
||||
activeKey={activeTab}
|
||||
onChange={setActiveTab}
|
||||
onChange={(key) => setActiveTab(key as CostCenterTab)}
|
||||
items={[
|
||||
{
|
||||
key: 'products',
|
||||
@@ -218,22 +206,25 @@ export default function CostCenterShell() {
|
||||
{
|
||||
key: 'mappings',
|
||||
label: '渠道映射',
|
||||
children: <ChannelMappingPanel />,
|
||||
children: mappingsApplicable ? (
|
||||
<ChannelMappingPanel />
|
||||
) : (
|
||||
<Alert
|
||||
type="info"
|
||||
showIcon
|
||||
message={`${scopeLabel}不维护渠道映射`}
|
||||
description={
|
||||
scope === 'affiliate_dash'
|
||||
? '自动发货的订单项直接按 aff:<skuCode> 归一,不经过渠道映射;要核对采购价请到「成本配置 → 自动发货采购价」。'
|
||||
: '人工客服的订单项按内部 SKU 归一(man: 前缀),不走渠道映射;要配置消耗积分请到「成本配置 → 人工客服 SKU」。'
|
||||
}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'affiliate-skus',
|
||||
label: '自动发货 SKU',
|
||||
children: <AffiliateSkuPanel />,
|
||||
},
|
||||
{
|
||||
key: 'manual-skus',
|
||||
label: '人工 SKU 配置',
|
||||
children: <ManualSkuConfigPanel />,
|
||||
},
|
||||
{
|
||||
key: 'prices',
|
||||
label: '发单价格',
|
||||
children: <WorkOrderPricePanel />,
|
||||
key: 'cost',
|
||||
label: '成本配置',
|
||||
children: <CostConfigPanel />,
|
||||
},
|
||||
{
|
||||
key: 'exceptions',
|
||||
@@ -249,7 +240,7 @@ export default function CostCenterShell() {
|
||||
),
|
||||
children: <CostExceptionPanel />,
|
||||
},
|
||||
].filter((item) => visibleTabKeys.includes(item.key))}
|
||||
]}
|
||||
/>
|
||||
</section>
|
||||
</CostCenterContext.Provider>
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* 成本配置:按来源展示「成本怎么算」。
|
||||
*
|
||||
* 三个来源的成本形态完全不同,所以这里不做统一表格,而是按来源切换:
|
||||
* 自动发货 → 上游 SKU 采购价(按 aff:<skuCode> 归一)
|
||||
* 接单平台 → 接单模板发单金额(只读核对,改价去接单模板页)
|
||||
* 人工客服 → 内部 SKU 的履约渠道与消耗积分
|
||||
*
|
||||
* 来源在页面顶部工具栏统一选择;选「全部」时这里给出三个入口,
|
||||
* 避免把三套配置竖着堆在一页里。
|
||||
*/
|
||||
import { Button, Card, Col, Row, Space, Typography } from 'antd'
|
||||
|
||||
import { AffiliateSkuPanel } from './AffiliateSkuPanel'
|
||||
import { useCostCenter } from './CostCenterContext'
|
||||
import { ManualSkuConfigPanel } from './ManualSkuConfigPanel'
|
||||
import { WorkOrderPricePanel } from './WorkOrderPricePanel'
|
||||
import type { CostScope } from './shared'
|
||||
|
||||
const CONFIG_ENTRIES: Array<{
|
||||
key: Exclude<CostScope, 'all'>
|
||||
title: string
|
||||
description: string
|
||||
}> = [
|
||||
{
|
||||
key: 'affiliate_dash',
|
||||
title: '自动发货采购价',
|
||||
description: '按上游货源 SKU 配采购成本,订单项直接按 aff:<skuCode> 归一,不走渠道映射。',
|
||||
},
|
||||
{
|
||||
key: 'work_order',
|
||||
title: '接单平台发单金额',
|
||||
description: '接单模板 → 发单金额的当前生效版本,只读核对;改价请改模板后重新同步。',
|
||||
},
|
||||
{
|
||||
key: 'manual',
|
||||
title: '人工客服 SKU 消耗',
|
||||
description: '内部 SKU 的履约渠道与消耗积分;积分填 0 表示成本不固定,确认履约时手填。',
|
||||
},
|
||||
]
|
||||
|
||||
export default function CostConfigPanel() {
|
||||
const { scope, setScope } = useCostCenter()
|
||||
|
||||
if (scope === 'affiliate_dash') return <AffiliateSkuPanel />
|
||||
if (scope === 'work_order') return <WorkOrderPricePanel />
|
||||
if (scope === 'manual') return <ManualSkuConfigPanel />
|
||||
|
||||
return (
|
||||
<Space direction="vertical" size={12} style={{ width: '100%' }}>
|
||||
<Typography.Text type="secondary">
|
||||
成本配置按来源分开维护,选择一个来源查看;也可以在页面顶部直接切换来源。
|
||||
</Typography.Text>
|
||||
<Row gutter={[12, 12]}>
|
||||
{CONFIG_ENTRIES.map((entry) => (
|
||||
<Col xs={24} xl={8} key={entry.key}>
|
||||
<Card
|
||||
size="small"
|
||||
title={entry.title}
|
||||
extra={
|
||||
<Button size="small" type="primary" onClick={() => setScope(entry.key)}>
|
||||
去配置
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<Typography.Text type="secondary">{entry.description}</Typography.Text>
|
||||
</Card>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</Space>
|
||||
)
|
||||
}
|
||||
+1
-1
@@ -127,7 +127,7 @@
|
||||
| --- | --- | --- |
|
||||
| [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) | **现行唯一口径** | 履约方式、成本模型、人工全覆盖、历史策略、实施顺序、运营日检与验收 SQL |
|
||||
| [成本中心与履约模型.md](成本中心与履约模型.md) | 现行 | 商品、成本版本、快照、异常、销售事实的数据模型;迁移 `103`–`107`;履约回填;迁移基线与本地库同步;索引与性能 |
|
||||
| [成本中心API契约.md](成本中心API契约.md) | 现行 | 成本中心接口字段替换总表、枚举、模块边界(后端 5 模块 + 前端 8 面板) |
|
||||
| [成本中心API契约.md](成本中心API契约.md) | 现行 | 成本中心接口字段替换总表、枚举、模块边界(后端 5 模块 + 前端 4 个固定 Tab) |
|
||||
| [人工支出与备用金.md](人工支出与备用金.md) | 现行(P0 已实施) | 确认履约流程/权限、客服备用金台账、本人账户与编号规则 |
|
||||
| [财务系统集成方案.md](财务系统集成方案.md) | 现行方案(总账未实施) | 复式记账、总账表、对账、关账 |
|
||||
| [影子总账说明.md](影子总账说明.md) | 现行说明(未实施) | 影子总账是什么、和钱包流水的区别、对账与转正标准 |
|
||||
|
||||
+2
-1
@@ -276,7 +276,8 @@ AND (
|
||||
| `pages/admin/cost-center/CostCenterContext.ts` | 页面上下文(`useCostCenter`) |
|
||||
| `pages/admin/cost-center/ProductCatalogPanel.tsx` | 标准商品 Tab |
|
||||
| `pages/admin/cost-center/ChannelMappingPanel.tsx` | 渠道映射 Tab |
|
||||
| `pages/admin/cost-center/AffiliateSkuPanel.tsx` | 自动发货 SKU Tab |
|
||||
| `pages/admin/cost-center/CostConfigPanel.tsx` | 成本配置 Tab(按来源切换下面三个) |
|
||||
| `pages/admin/cost-center/AffiliateSkuPanel.tsx` | 自动发货采购价(成本配置内) |
|
||||
| `pages/admin/cost-center/CostItemPanel.tsx` | 成本项 Tab |
|
||||
| `pages/admin/cost-center/CostVersionPanel.tsx` | 成本版本 Tab |
|
||||
| `pages/admin/cost-center/CostExceptionPanel.tsx` | 成本异常 Tab |
|
||||
|
||||
Reference in New Issue
Block a user