feat(energy): 氢/电统一时间速选为「本周/本月/近15天」+ 缺失日补 0
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- 后端 Range 类型精简到 thisWeek / thisMonth / last15 rangeClause 同步精简;删除 today / thisQuarter / last7 / last30 分支 - 新增 enumerateDates(range):列出 range 内全部日期,用于补零 - /hydrogen/daily:用 enumerateDates 补齐缺失日期 totalKg=0、stations=[] 补零后基于完整日期序列重算环比(0→上一日有值时显示 -100%) - /electric/monthly:增加 range 参数,扁平日聚合 + 月份分组 缺失日期同样补零;环比基于补零序列重算 - 默认 range 改 last15 前端 - HydrogenDaily QUICK_PICK_OPTIONS 收紧到 3 项,默认 last15 - ElectricDaily 之前没有日期速选,现按氢能样式加上同样 3 项 类型 DateQuickPick 改 'thisWeek' | 'thisMonth' | 'last15' Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,11 +3,18 @@ import { ChevronRight } from 'lucide-react';
|
||||
import { motion, AnimatePresence } from 'motion/react';
|
||||
import TrendBadge from './TrendBadge';
|
||||
import { fetchElectricMonthly } from './api';
|
||||
import type { CustomerType, ElectricMonthGroup } from './types';
|
||||
import type { CustomerType, DateQuickPick, ElectricMonthGroup } from './types';
|
||||
import RotatingFooterHint from '../../components/RotatingFooterHint';
|
||||
|
||||
const QUICK_PICK_OPTIONS: Array<{ id: DateQuickPick; label: string }> = [
|
||||
{ id: 'thisWeek', label: '本周' },
|
||||
{ id: 'thisMonth', label: '本月' },
|
||||
{ id: 'last15', label: '近 15 天' },
|
||||
];
|
||||
|
||||
export default function ElectricDaily() {
|
||||
const [customer, setCustomer] = useState<CustomerType>('lingniu');
|
||||
const [pick, setPick] = useState<DateQuickPick>('last15');
|
||||
const [months, setMonths] = useState<ElectricMonthGroup[] | null>(null);
|
||||
const [openMonths, setOpenMonths] = useState<Set<string>>(new Set());
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
@@ -15,7 +22,7 @@ export default function ElectricDaily() {
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
setError(null);
|
||||
fetchElectricMonthly(customer)
|
||||
fetchElectricMonthly(customer, pick)
|
||||
.then(m => {
|
||||
if (cancelled) return;
|
||||
setMonths(m);
|
||||
@@ -24,7 +31,7 @@ export default function ElectricDaily() {
|
||||
})
|
||||
.catch(e => { if (!cancelled) setError(e instanceof Error ? e.message : String(e)); });
|
||||
return () => { cancelled = true; };
|
||||
}, [customer]);
|
||||
}, [customer, pick]);
|
||||
|
||||
const toggleMonth = (m: string) => setOpenMonths(prev => {
|
||||
const next = new Set(prev);
|
||||
@@ -34,6 +41,23 @@ export default function ElectricDaily() {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
{/* 日期速选 */}
|
||||
<div className="flex items-center gap-2 overflow-x-auto -mx-1 px-1 pb-1 snap-x">
|
||||
{QUICK_PICK_OPTIONS.map(opt => (
|
||||
<button
|
||||
key={opt.id}
|
||||
onClick={() => setPick(opt.id)}
|
||||
className={`shrink-0 snap-start rounded-xl px-3 py-1.5 text-[11px] font-bold border transition-colors ${
|
||||
pick === opt.id
|
||||
? 'bg-blue-50 text-blue-600 border-blue-200'
|
||||
: 'bg-white text-slate-500 border-slate-200 hover:bg-slate-50'
|
||||
}`}
|
||||
>
|
||||
{opt.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* 客户类型 */}
|
||||
<div className="bg-slate-100 rounded-xl p-1 grid grid-cols-2 gap-1">
|
||||
{(['lingniu', 'external'] as const).map(c => (
|
||||
|
||||
@@ -8,16 +8,13 @@ import type { CustomerType, DateQuickPick, HydrogenDailyRow } from './types';
|
||||
import RotatingFooterHint from '../../components/RotatingFooterHint';
|
||||
|
||||
const QUICK_PICK_OPTIONS: Array<{ id: DateQuickPick; label: string }> = [
|
||||
{ id: 'today', label: '当天' },
|
||||
{ id: 'thisWeek', label: '本周' },
|
||||
{ id: 'thisMonth', label: '本月' },
|
||||
{ id: 'thisQuarter', label: '本季度' },
|
||||
{ id: 'last7', label: '最近7天' },
|
||||
{ id: 'last30', label: '最近30天' },
|
||||
{ id: 'thisWeek', label: '本周' },
|
||||
{ id: 'thisMonth', label: '本月' },
|
||||
{ id: 'last15', label: '近 15 天' },
|
||||
];
|
||||
|
||||
export default function HydrogenDaily() {
|
||||
const [pick, setPick] = useState<DateQuickPick>('last30');
|
||||
const [pick, setPick] = useState<DateQuickPick>('last15');
|
||||
const [customer, setCustomer] = useState<CustomerType>('lingniu');
|
||||
const [expanded, setExpanded] = useState<Set<string>>(new Set());
|
||||
const [rows, setRows] = useState<HydrogenDailyRow[] | null>(null);
|
||||
|
||||
@@ -31,7 +31,7 @@ export function fetchElectricOverview(): Promise<ElectricOverviewResponse> {
|
||||
return fetchJson<ElectricOverviewResponse>(`${BASE}/electric/overview`);
|
||||
}
|
||||
|
||||
export function fetchElectricMonthly(customer: CustomerType): Promise<ElectricMonthGroup[]> {
|
||||
const q = new URLSearchParams({ customer });
|
||||
export function fetchElectricMonthly(customer: CustomerType, range: DateQuickPick = 'last15'): Promise<ElectricMonthGroup[]> {
|
||||
const q = new URLSearchParams({ customer, range });
|
||||
return fetchJson<ElectricMonthGroup[]>(`${BASE}/electric/monthly?${q.toString()}`);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export type CustomerType = 'external' | 'lingniu';
|
||||
export type DateQuickPick = 'today' | 'thisWeek' | 'thisMonth' | 'thisQuarter' | 'last7' | 'last30';
|
||||
export type DateQuickPick = 'thisWeek' | 'thisMonth' | 'last15';
|
||||
|
||||
export interface HydrogenKpi {
|
||||
yearKg: number;
|
||||
|
||||
Reference in New Issue
Block a user