diff --git a/apps/backend/src/services/cost-center/cost-center-overview-service.ts b/apps/backend/src/services/cost-center/cost-center-overview-service.ts
index 3c8f58c4..afc47bf1 100644
--- a/apps/backend/src/services/cost-center/cost-center-overview-service.ts
+++ b/apps/backend/src/services/cost-center/cost-center-overview-service.ts
@@ -89,12 +89,11 @@ export async function getAdminCostCenterOverview(params: { scope?: string } = {}
(
SELECT COUNT(*)::int
FROM cost_exceptions ce
+ JOIN order_items oi ON oi.id = ce.order_item_id
WHERE ce.status = 'open'
AND (
$1::text IS NULL
- OR ce.order_item_id IN (
- SELECT oi.id FROM order_items oi WHERE COALESCE(oi.fulfillment_channel, CASE WHEN oi.fulfillment_status = 'archived' THEN 'archived' ELSE 'pending' END) = $1
- )
+ OR COALESCE(oi.fulfillment_channel, CASE WHEN oi.fulfillment_status = 'archived' THEN 'archived' ELSE 'pending' END) = $1
)
) AS open_exception_count,
(
diff --git a/apps/backend/src/services/cost-center/cost-center.test.ts b/apps/backend/src/services/cost-center/cost-center.test.ts
index 56cdba0c..c65bbe97 100644
--- a/apps/backend/src/services/cost-center/cost-center.test.ts
+++ b/apps/backend/src/services/cost-center/cost-center.test.ts
@@ -298,6 +298,16 @@ test('人工客服筛选排除已有其他主渠道的旧 man 商品', () => {
assert.ok(sql.includes('BTRIM(live_channel.internal_sku) = BTRIM(p.canonical_name)'))
})
+test('成本中心总览异常统计必须走异常表关联,不能全表扫描订单项子查询', async () => {
+ const { readFile } = await import('node:fs/promises')
+ const source = await readFile(
+ new URL('./cost-center-overview-service.ts', import.meta.url),
+ 'utf8',
+ )
+ assert.ok(source.includes('JOIN order_items oi ON oi.id = ce.order_item_id'))
+ assert.ok(!source.includes('ce.order_item_id IN ('))
+})
+
test('tpv: 商品来源归为第三方卡券', async () => {
const { productSourceOf } = await import('./cost-center-mappers.js')
const assert = (await import('node:assert/strict')).default
diff --git a/apps/frontend/src/pages/admin/cost-center/CostCenterShell.tsx b/apps/frontend/src/pages/admin/cost-center/CostCenterShell.tsx
index 42edb0df..9981a5f3 100644
--- a/apps/frontend/src/pages/admin/cost-center/CostCenterShell.tsx
+++ b/apps/frontend/src/pages/admin/cost-center/CostCenterShell.tsx
@@ -22,7 +22,7 @@ import {
Tag,
Typography,
} from 'antd'
-import { useQuery, useQueryClient } from '@tanstack/react-query'
+import { keepPreviousData, useIsFetching, useQuery, useQueryClient } from '@tanstack/react-query'
import { useEffect } from 'react'
import FinanceSubNav from '@/components/admin/FinanceSubNav'
@@ -97,6 +97,7 @@ export default function CostCenterShell() {
const overviewQuery = useQuery({
queryKey: ['admin-cost-center-overview', scope],
queryFn: () => fetchAdminCostCenterOverview({ scope }),
+ placeholderData: keepPreviousData,
})
const optionsQuery = useQuery({
queryKey: ['admin-cost-center-options'],
@@ -105,6 +106,9 @@ export default function CostCenterShell() {
const overview = overviewQuery.data?.data
const options = optionsQuery.data?.data
+ const costCenterFetching = useIsFetching({
+ predicate: (query) => String(query.queryKey[0] ?? '').startsWith('admin-cost-center'),
+ })
function refreshAll() {
// 按前缀失效:新增一个 admin-cost-center-* 查询不需要再回来改这里。
@@ -145,7 +149,7 @@ export default function CostCenterShell() {
size="small"
icon={