diff --git a/client/src/components/cost-analysis/StoreTab.tsx b/client/src/components/cost-analysis/StoreTab.tsx index 3179955..28eb3d2 100644 --- a/client/src/components/cost-analysis/StoreTab.tsx +++ b/client/src/components/cost-analysis/StoreTab.tsx @@ -8,6 +8,7 @@ import { Pagination } from '@/components/Pagination' import { formatCurrency, formatPercent, formatNumber } from '@/lib/utils' import { useState } from 'react' import { PieChart, Pie, Cell, Tooltip, ResponsiveContainer } from 'recharts' +import { MonthPicker } from '@/components/MonthPicker' const PAGE_SIZE = 15 const LEVEL_COLORS: Record = { @@ -22,9 +23,10 @@ export function StoreTab() { const [sort, setSort] = useState('food_cost_variance') const [order, setOrder] = useState('desc') const [filter, setFilter] = useState('') + const [month, setMonth] = useState('2026-04') - const { data: ov, isLoading: l1 } = useQuery({ queryKey: ['ca/store-overview'], queryFn: () => api.get('/cost-analysis/store-overview') }) - const { data: ranking, isLoading: l2 } = useQuery({ queryKey: ['ca/store-ranking', page, sort, order, filter], queryFn: () => api.get(`/cost-analysis/store-ranking?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&order=${order}&filter=${filter}`) }) + const { data: ov, isLoading: l1 } = useQuery({ queryKey: ['ca/store-overview', month], queryFn: () => api.get('/cost-analysis/store-overview', { params: { month } }) }) + const { data: ranking, isLoading: l2 } = useQuery({ queryKey: ['ca/store-ranking', month, page, sort, order, filter], queryFn: () => api.get(`/cost-analysis/store-ranking?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&order=${order}&filter=${filter}&month=${month}`) }) if (l1 || l2) return @@ -48,6 +50,9 @@ export function StoreTab() { return (
+
+ +
diff --git a/client/src/components/store-expense/BreakEvenTab.tsx b/client/src/components/store-expense/BreakEvenTab.tsx index 68d3802..fc1d534 100644 --- a/client/src/components/store-expense/BreakEvenTab.tsx +++ b/client/src/components/store-expense/BreakEvenTab.tsx @@ -17,12 +17,12 @@ const SAFETY_COLORS: Record = { '安全边际充足': 'text-green-600', } -export function BreakEvenTab() { +export function BreakEvenTab({ month }: { month: string }) { const [page, setPage] = useState(1) const [sort, setSort] = useState('safety_margin_pct') const [filter, setFilter] = useState('') const [order, setOrder] = useState('asc') - const { data, isLoading } = useQuery({ queryKey: ['se/break-even', page, sort, filter, order], queryFn: () => api.get(`/store-expense/break-even?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&order=${order}`) }) + const { data, isLoading } = useQuery({ queryKey: ['se/break-even', month, page, sort, filter, order], queryFn: () => api.get(`/store-expense/break-even?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&order=${order}&month=${month}`) }) if (isLoading) return diff --git a/client/src/components/store-expense/ContributionTab.tsx b/client/src/components/store-expense/ContributionTab.tsx index 34652f8..da212bb 100644 --- a/client/src/components/store-expense/ContributionTab.tsx +++ b/client/src/components/store-expense/ContributionTab.tsx @@ -9,12 +9,12 @@ import { formatCurrency, formatPercent } from '@/lib/utils' const PAGE_SIZE = 20 -export function ContributionTab() { +export function ContributionTab({ month }: { month: string }) { const [page, setPage] = useState(1) const [sort, setSort] = useState('actual_store_contribution_rate_pct') const [filter, setFilter] = useState('') const [order, setOrder] = useState('asc') - const { data, isLoading } = useQuery({ queryKey: ['se/contribution', page, sort, filter, order], queryFn: () => api.get(`/store-expense/store-contribution?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&order=${order}`) }) + const { data, isLoading } = useQuery({ queryKey: ['se/contribution', month, page, sort, filter, order], queryFn: () => api.get(`/store-expense/store-contribution?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&order=${order}&month=${month}`) }) if (isLoading) return diff --git a/client/src/components/store-expense/DeliveryTab.tsx b/client/src/components/store-expense/DeliveryTab.tsx index 2c83525..85426c1 100644 --- a/client/src/components/store-expense/DeliveryTab.tsx +++ b/client/src/components/store-expense/DeliveryTab.tsx @@ -9,12 +9,12 @@ import { formatCurrency, formatPercent } from '@/lib/utils' const PAGE_SIZE = 20 -export function DeliveryTab() { +export function DeliveryTab({ month }: { month: string }) { const [page, setPage] = useState(1) const [sort, setSort] = useState('commission_to_delivery_sales_pct') const [filter, setFilter] = useState('') const [order, setOrder] = useState('desc') - const { data, isLoading } = useQuery({ queryKey: ['se/delivery', page, sort, filter, order], queryFn: () => api.get(`/store-expense/delivery-commission?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&order=${order}`) }) + const { data, isLoading } = useQuery({ queryKey: ['se/delivery', month, page, sort, filter, order], queryFn: () => api.get(`/store-expense/delivery-commission?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&order=${order}&month=${month}`) }) if (isLoading) return diff --git a/client/src/components/store-expense/EfficiencyTab.tsx b/client/src/components/store-expense/EfficiencyTab.tsx index f7f6a45..03ccb24 100644 --- a/client/src/components/store-expense/EfficiencyTab.tsx +++ b/client/src/components/store-expense/EfficiencyTab.tsx @@ -9,12 +9,12 @@ import { formatCurrency, formatPercent, formatNumber } from '@/lib/utils' const PAGE_SIZE = 20 -export function EfficiencyTab() { +export function EfficiencyTab({ month }: { month: string }) { const [page, setPage] = useState(1) const [sort, setSort] = useState('received_per_sqm') const [filter, setFilter] = useState('') const [order, setOrder] = useState('desc') - const { data, isLoading } = useQuery({ queryKey: ['se/efficiency', page, sort, filter, order], queryFn: () => api.get(`/store-expense/efficiency?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&order=${order}`) }) + const { data, isLoading } = useQuery({ queryKey: ['se/efficiency', month, page, sort, filter, order], queryFn: () => api.get(`/store-expense/efficiency?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&order=${order}&month=${month}`) }) if (isLoading) return diff --git a/client/src/components/store-expense/ExpenseOverviewTab.tsx b/client/src/components/store-expense/ExpenseOverviewTab.tsx index 8ff2bfc..d4306a6 100644 --- a/client/src/components/store-expense/ExpenseOverviewTab.tsx +++ b/client/src/components/store-expense/ExpenseOverviewTab.tsx @@ -8,9 +8,9 @@ import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContaine const PIE_COLORS = ['#3b82f6', '#ef4444', '#22c55e', '#f97316', '#eab308', '#8b5cf6', '#06b6d4', '#ec4899', '#84cc16', '#a3a3a3', '#f43f5e', '#6366f1', '#14b8a6', '#facc15', '#7c3aed', '#10b981', '#fb923c'] -export function ExpenseOverviewTab() { - const { data: overview, isLoading: l1 } = useQuery({ queryKey: ['se/overview'], queryFn: () => api.get('/store-expense/overview') }) - const { data: structure, isLoading: l2 } = useQuery({ queryKey: ['se/structure'], queryFn: () => api.get('/store-expense/expense-structure') }) +export function ExpenseOverviewTab({ month }: { month: string }) { + const { data: overview, isLoading: l1 } = useQuery({ queryKey: ['se/overview', month], queryFn: () => api.get('/store-expense/overview', { params: { month } }) }) + const { data: structure, isLoading: l2 } = useQuery({ queryKey: ['se/structure', month], queryFn: () => api.get('/store-expense/expense-structure', { params: { month } }) }) if (l1 || l2) return diff --git a/client/src/components/store-expense/FixedVariableTab.tsx b/client/src/components/store-expense/FixedVariableTab.tsx index 93d5e63..1426a1b 100644 --- a/client/src/components/store-expense/FixedVariableTab.tsx +++ b/client/src/components/store-expense/FixedVariableTab.tsx @@ -9,12 +9,12 @@ import { formatCurrency, formatPercent } from '@/lib/utils' const PAGE_SIZE = 20 -export function FixedVariableTab() { +export function FixedVariableTab({ month }: { month: string }) { const [page, setPage] = useState(1) const [sort, setSort] = useState('fixed_rate_pct') const [filter, setFilter] = useState('') const [order, setOrder] = useState('desc') - const { data, isLoading } = useQuery({ queryKey: ['se/fixed-variable', page, sort, filter, order], queryFn: () => api.get(`/store-expense/fixed-variable?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&order=${order}`) }) + const { data, isLoading } = useQuery({ queryKey: ['se/fixed-variable', month, page, sort, filter, order], queryFn: () => api.get(`/store-expense/fixed-variable?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&order=${order}&month=${month}`) }) if (isLoading) return diff --git a/client/src/components/store-expense/LossDiagnosisTab.tsx b/client/src/components/store-expense/LossDiagnosisTab.tsx index 34c396e..b9e8cdf 100644 --- a/client/src/components/store-expense/LossDiagnosisTab.tsx +++ b/client/src/components/store-expense/LossDiagnosisTab.tsx @@ -185,13 +185,13 @@ function StoreDetailModal({ store, onClose }: { store: StoreDetail | null, onClo ) } -export function LossDiagnosisTab() { +export function LossDiagnosisTab({ month }: { month: string }) { const [page, setPage] = useState(1) const [sort, setSort] = useState('actual_store_contribution') const [filter, setFilter] = useState('') const [order, setOrder] = useState('asc') const [selectedStore, setSelectedStore] = useState(null) - const { data, isLoading } = useQuery({ queryKey: ['se/loss-diagnosis', page, sort, filter, order], queryFn: () => api.get(`/store-expense/loss-diagnosis?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&order=${order}`) }) + const { data, isLoading } = useQuery({ queryKey: ['se/loss-diagnosis', month, page, sort, filter, order], queryFn: () => api.get(`/store-expense/loss-diagnosis?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&order=${order}&month=${month}`) }) if (isLoading) return diff --git a/client/src/components/store-expense/RentRiskTab.tsx b/client/src/components/store-expense/RentRiskTab.tsx index 5e7e9b6..6b2e231 100644 --- a/client/src/components/store-expense/RentRiskTab.tsx +++ b/client/src/components/store-expense/RentRiskTab.tsx @@ -17,13 +17,13 @@ const RISK_COLORS: Record = { '正常': '', } -export function RentRiskTab() { +export function RentRiskTab({ month }: { month: string }) { const [page, setPage] = useState(1) const [sort, setSort] = useState('rent_rate_pct') const [filter, setFilter] = useState('') const [riskOnly, setRiskOnly] = useState(false) const [order, setOrder] = useState('desc') - const { data, isLoading } = useQuery({ queryKey: ['se/rent', page, sort, filter, riskOnly, order], queryFn: () => api.get(`/store-expense/rent-risk?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&risk_only=${riskOnly}&order=${order}`) }) + const { data, isLoading } = useQuery({ queryKey: ['se/rent', month, page, sort, filter, riskOnly, order], queryFn: () => api.get(`/store-expense/rent-risk?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&risk_only=${riskOnly}&order=${order}&month=${month}`) }) if (isLoading) return diff --git a/client/src/components/store-expense/StoreEvaluationTab.tsx b/client/src/components/store-expense/StoreEvaluationTab.tsx index b2b60a9..50107f3 100644 --- a/client/src/components/store-expense/StoreEvaluationTab.tsx +++ b/client/src/components/store-expense/StoreEvaluationTab.tsx @@ -107,13 +107,13 @@ function EvalDetailModal({ store, onClose }: { store: EvalStoreDetail | null, on ) } -export function StoreEvaluationTab() { +export function StoreEvaluationTab({ month }: { month: string }) { const [page, setPage] = useState(1) const [sort, setSort] = useState('actual_store_contribution_rate_pct') const [filter, setFilter] = useState('') const [order, setOrder] = useState('asc') const [selectedStore, setSelectedStore] = useState(null) - const { data, isLoading } = useQuery({ queryKey: ['se/evaluation', page, sort, filter, order], queryFn: () => api.get(`/store-expense/store-evaluation?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&order=${order}`) }) + const { data, isLoading } = useQuery({ queryKey: ['se/evaluation', month, page, sort, filter, order], queryFn: () => api.get(`/store-expense/store-evaluation?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&order=${order}&month=${month}`) }) if (isLoading) return diff --git a/client/src/components/store-expense/StoreRankingTab.tsx b/client/src/components/store-expense/StoreRankingTab.tsx index 662c85e..50d12ac 100644 --- a/client/src/components/store-expense/StoreRankingTab.tsx +++ b/client/src/components/store-expense/StoreRankingTab.tsx @@ -9,13 +9,13 @@ import { formatCurrency, formatPercent, formatNumber } from '@/lib/utils' const PAGE_SIZE = 20 -export function StoreRankingTab() { +export function StoreRankingTab({ month }: { month: string }) { const [page, setPage] = useState(1) const [sort, setSort] = useState('operating_expense_rate_pct') const [filter, setFilter] = useState('') const [order, setOrder] = useState('desc') - const { data, isLoading } = useQuery({ queryKey: ['se/ranking', page, sort, filter, order], queryFn: () => api.get(`/store-expense/store-ranking?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&order=${order}`) }) + const { data, isLoading } = useQuery({ queryKey: ['se/ranking', month, page, sort, filter, order], queryFn: () => api.get(`/store-expense/store-ranking?page=${page}&page_size=${PAGE_SIZE}&sort=${sort}&filter=${filter}&order=${order}&month=${month}`) }) if (isLoading) return diff --git a/client/src/pages/CostPage.tsx b/client/src/pages/CostPage.tsx index 9c1ecf7..dc8b140 100644 --- a/client/src/pages/CostPage.tsx +++ b/client/src/pages/CostPage.tsx @@ -9,6 +9,7 @@ import { Badge } from '@/components/Badge' import { formatCurrency, formatNumber, formatPercent } from '@/lib/utils' import { useState, useMemo } from 'react' import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, ScatterChart, Scatter } from 'recharts' +import { MonthPicker } from '@/components/MonthPicker' const PAGE_SIZE = 15 @@ -16,20 +17,21 @@ export function CostPage() { const [costPage, setCostPage] = useState(1) const [invPage, setInvPage] = useState(1) const [catPage, setCatPage] = useState(1) + const [month, setMonth] = useState('2026-04') const { data: costData, isLoading: costLoading } = useQuery({ - queryKey: ['cost/comparison'], - queryFn: () => api.get('/cost/comparison'), + queryKey: ['cost/comparison', month], + queryFn: () => api.get('/cost/comparison', { params: { month } }), }) const { data: invData, isLoading: invLoading } = useQuery({ - queryKey: ['cost/inventory'], - queryFn: () => api.get('/cost/inventory'), + queryKey: ['cost/inventory', month], + queryFn: () => api.get('/cost/inventory', { params: { month } }), }) const { data: catData, isLoading: catLoading } = useQuery({ - queryKey: ['cost/category-benchmark'], - queryFn: () => api.get('/cost/category-benchmark'), + queryKey: ['cost/category-benchmark', month], + queryFn: () => api.get('/cost/category-benchmark', { params: { month } }), }) const costRows = (costData as any)?.data || [] @@ -67,9 +69,12 @@ export function CostPage() { return (
-
-

成本与库存管理

-

理论vs实际成本 · 原料分类差异 · 库存效率 · 2026年4月

+
+
+

成本与库存管理

+

理论vs实际成本 · 原料分类差异 · 库存效率 · {month}

+
+
{/* 概览指标 */} diff --git a/client/src/pages/DataQualityPage.tsx b/client/src/pages/DataQualityPage.tsx index af65177..d9a661d 100644 --- a/client/src/pages/DataQualityPage.tsx +++ b/client/src/pages/DataQualityPage.tsx @@ -4,11 +4,14 @@ import { LoadingSpinner } from '@/components/LoadingSpinner' import { CollapsibleSection } from '@/components/CollapsibleSection' import { MetricCard } from '@/components/MetricCard' import { formatNumber, formatCurrency } from '@/lib/utils' +import { useState } from 'react' +import { MonthPicker } from '@/components/MonthPicker' export function DataQualityPage() { + const [month, setMonth] = useState('2026-04') const { data: qualityData, isLoading } = useQuery({ - queryKey: ['data-quality'], - queryFn: () => api.get('/data-quality'), + queryKey: ['data-quality', month], + queryFn: () => api.get('/data-quality', { params: { month } }), }) const dq = (qualityData as any)?.data || {} @@ -45,9 +48,12 @@ export function DataQualityPage() { return (
-
-

数据质量看板

-

账单与菜品明细数据质量检查 · {dq.min_date?.substring(0, 10)} ~ {dq.max_date?.substring(0, 10)}

+
+
+

数据质量看板

+

账单与菜品明细数据质量检查 · {dq.min_date?.substring(0, 10)} ~ {dq.max_date?.substring(0, 10)}

+
+
{/* 质量状态总览 */} diff --git a/client/src/pages/MemberPage.tsx b/client/src/pages/MemberPage.tsx index 48ceab2..12e9fa4 100644 --- a/client/src/pages/MemberPage.tsx +++ b/client/src/pages/MemberPage.tsx @@ -8,11 +8,13 @@ import { MetricCard } from '@/components/MetricCard' import { formatCurrency, formatNumber, formatPercent } from '@/lib/utils' import { useState, useMemo } from 'react' import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, PieChart, Pie, Cell } from 'recharts' +import { MonthPicker } from '@/components/MonthPicker' const PAGE_SIZE = 15 export function MemberPage() { const [repeatPage, setRepeatPage] = useState(1) + const [month, setMonth] = useState('2026-04') const { data: comparisonData, isLoading: cmpLoading } = useQuery({ queryKey: ['member/comparison'], @@ -20,8 +22,8 @@ export function MemberPage() { }) const { data: repeatData, isLoading: repeatLoading } = useQuery({ - queryKey: ['member/repeat'], - queryFn: () => api.get('/member/repeat'), + queryKey: ['member/repeat', month], + queryFn: () => api.get('/member/repeat', { params: { month } }), }) const cmpRows = (comparisonData as any)?.data || [] @@ -66,9 +68,12 @@ export function MemberPage() { return (
-
-

会员与复购管理

-

会员对比 · 复购率 · 沉睡分析 · 2026年4月

+
+
+

会员与复购管理

+

会员对比 · 复购率 · 沉睡分析 · {month}

+
+
{/* 概览指标 */} diff --git a/client/src/pages/PlatformPage.tsx b/client/src/pages/PlatformPage.tsx index a3e0c92..bee1b1a 100644 --- a/client/src/pages/PlatformPage.tsx +++ b/client/src/pages/PlatformPage.tsx @@ -8,16 +8,18 @@ import { MetricCard } from '@/components/MetricCard' import { formatCurrency, formatNumber, formatPercent } from '@/lib/utils' import { useState, useMemo } from 'react' import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts' +import { MonthPicker } from '@/components/MonthPicker' const PAGE_SIZE = 15 export function PlatformPage() { const [platformPage, setPlatformPage] = useState(1) const [marketingPage, setMarketingPage] = useState(1) + const [month, setMonth] = useState('2026-04') const { data: platformData, isLoading: platformLoading } = useQuery({ - queryKey: ['platform/economics'], - queryFn: () => api.get('/platform/economics'), + queryKey: ['platform/economics', month], + queryFn: () => api.get('/platform/economics', { params: { month } }), }) const { data: marketingData, isLoading: marketingLoading } = useQuery({ @@ -63,9 +65,12 @@ export function PlatformPage() { return (
-
-

平台与优惠管理

-

三平台经济性 · 营销方案ROI · 优惠结构 · 2026年4月

+
+
+

平台与优惠管理

+

三平台经济性 · 营销方案ROI · 优惠结构 · {month}

+
+
{/* 概览指标 */} diff --git a/client/src/pages/SKUPage.tsx b/client/src/pages/SKUPage.tsx index 336667c..f132c21 100644 --- a/client/src/pages/SKUPage.tsx +++ b/client/src/pages/SKUPage.tsx @@ -8,6 +8,7 @@ import { MetricCard } from '@/components/MetricCard' import { formatCurrency, formatNumber, formatPercent } from '@/lib/utils' import { useState, useMemo } from 'react' import { PieChart, Pie, Cell, Tooltip, Legend, ResponsiveContainer, BarChart, Bar, XAxis, YAxis, CartesianGrid } from 'recharts' +import { MonthPicker } from '@/components/MonthPicker' const ABC_COLORS = { 'A-核心': '#22c55e', 'B-成长': '#3b82f6', 'C-长尾': '#ef4444' } const PAGE_SIZE = 15 @@ -15,10 +16,11 @@ const PAGE_SIZE = 15 export function SKUPage() { const [abcFilter, setAbcFilter] = useState('') const [skuPage, setSkuPage] = useState(1) + const [month, setMonth] = useState('2026-04') const { data: skuData, isLoading: skuLoading } = useQuery({ - queryKey: ['sku/abc'], - queryFn: () => api.get('/sku/abc'), + queryKey: ['sku/abc', month], + queryFn: () => api.get('/sku/abc', { params: { month } }), }) const { data: catData, isLoading: catLoading } = useQuery({ @@ -61,9 +63,12 @@ export function SKUPage() { return (
-
-

商品SKU管理

-

SKU ABC分析 · 长尾治理 · 品类结构 · 2026年4月

+
+
+

商品SKU管理

+

SKU ABC分析 · 长尾治理 · 品类结构 · {month}

+
+
{/* 概览指标 */} diff --git a/client/src/pages/SiteSelectionPage.tsx b/client/src/pages/SiteSelectionPage.tsx index 4d31b74..ec31a76 100644 --- a/client/src/pages/SiteSelectionPage.tsx +++ b/client/src/pages/SiteSelectionPage.tsx @@ -10,6 +10,7 @@ import { formatCurrency, formatNumber, formatPercent } from '@/lib/utils' import { useState, useMemo } from 'react' import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, ScatterChart, Scatter, ZAxis, ReferenceLine, Cell } from 'recharts' import { StoreMap } from '@/components/StoreMap' +import { MonthPicker } from '@/components/MonthPicker' const PAGE_SIZE = 15 const SCENE_COLORS: Record = { @@ -33,30 +34,31 @@ export function SiteSelectionPage() { const [replPage, setReplPage] = useState(1) const [overlapPage, setOverlapPage] = useState(1) const [profilePage, setProfilePage] = useState(1) + const [month, setMonth] = useState('2026-04') const { data: profileData, isLoading: profileLoading } = useQuery({ - queryKey: ['site-selection/profile'], - queryFn: () => api.get('/site-selection/profile'), + queryKey: ['site-selection/profile', month], + queryFn: () => api.get('/site-selection/profile', { params: { month } }), }) const { data: segData, isLoading: segLoading } = useQuery({ - queryKey: ['site-selection/segment-benchmark'], - queryFn: () => api.get('/site-selection/segment-benchmark'), + queryKey: ['site-selection/segment-benchmark', month], + queryFn: () => api.get('/site-selection/segment-benchmark', { params: { month } }), }) const { data: replData, isLoading: replLoading } = useQuery({ - queryKey: ['site-selection/replication'], - queryFn: () => api.get('/site-selection/replication'), + queryKey: ['site-selection/replication', month], + queryFn: () => api.get('/site-selection/replication', { params: { month } }), }) const { data: overlapData, isLoading: overlapLoading } = useQuery({ - queryKey: ['site-selection/overlap-risk'], - queryFn: () => api.get('/site-selection/overlap-risk'), + queryKey: ['site-selection/overlap-risk', month], + queryFn: () => api.get('/site-selection/overlap-risk', { params: { month } }), }) const { data: districtData, isLoading: districtLoading } = useQuery({ - queryKey: ['site-selection/district-benchmark'], - queryFn: () => api.get('/site-selection/district-benchmark'), + queryKey: ['site-selection/district-benchmark', month], + queryFn: () => api.get('/site-selection/district-benchmark', { params: { month } }), }) const profileRows = ((profileData as any)?.data || []).filter((r: any) => !sceneFilter || r.site_scene === sceneFilter) @@ -90,9 +92,12 @@ export function SiteSelectionPage() { return (
-
-

门店选址分析

-

基于全部现有数据的选址决策支持 · 2026年4月 · 91家经营门店

+
+
+

门店选址分析

+

基于现有数据的选址决策支持 · {month} · {totalStores}家经营门店

+
+
{/* 门店分布地图(左) + 指标+面积坪效分布(右) 左右并排 */} diff --git a/client/src/pages/StoreExpensePage.tsx b/client/src/pages/StoreExpensePage.tsx index 8c340f1..d2985d0 100644 --- a/client/src/pages/StoreExpensePage.tsx +++ b/client/src/pages/StoreExpensePage.tsx @@ -1,5 +1,6 @@ import { useState } from 'react' import { Tabs } from '@/components/Tabs' +import { MonthPicker } from '@/components/MonthPicker' import { ExpenseOverviewTab } from '@/components/store-expense/ExpenseOverviewTab' import { StoreRankingTab } from '@/components/store-expense/StoreRankingTab' import { ContributionTab } from '@/components/store-expense/ContributionTab' @@ -26,27 +27,31 @@ const TABS = [ export function StoreExpensePage() { const [activeTab, setActiveTab] = useState('overview') + const [month, setMonth] = useState('2026-04') return (
-
-

门店营业费用分析

-

2026年4月 · 89家经营门店 · 费用合计 ¥31,811,801

+
+
+

门店营业费用分析

+

{month} · 费用结构与贡献分析

+
+
- {activeTab === 'overview' && } - {activeTab === 'ranking' && } - {activeTab === 'contribution' && } - {activeTab === 'rent' && } - {activeTab === 'delivery' && } - {activeTab === 'efficiency' && } - {activeTab === 'fixed-variable' && } - {activeTab === 'break-even' && } - {activeTab === 'loss-diagnosis' && } - {activeTab === 'evaluation' && } + {activeTab === 'overview' && } + {activeTab === 'ranking' && } + {activeTab === 'contribution' && } + {activeTab === 'rent' && } + {activeTab === 'delivery' && } + {activeTab === 'efficiency' && } + {activeTab === 'fixed-variable' && } + {activeTab === 'break-even' && } + {activeTab === 'loss-diagnosis' && } + {activeTab === 'evaluation' && }
)