fix: 里程范围筛选接入后端

- 后端支持 mileageMin/mileageMax 查询参数
- 前端点击"完成筛选"时将里程范围提交到后端
- "重置所有"同时清除已应用的里程范围

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
kkfluous
2026-04-01 23:14:56 +08:00
parent 863ab17b58
commit 2469da310d
3 changed files with 20 additions and 3 deletions

View File

@@ -104,6 +104,7 @@ export default function MonitoringView() {
const [filterEntity, setFilterEntity] = useState('All'); const [filterEntity, setFilterEntity] = useState('All');
const [filterRegionCode, setFilterRegionCode] = useState('All'); const [filterRegionCode, setFilterRegionCode] = useState('All');
const [filterMileageRange, setFilterMileageRange] = useState({ min: '', max: '' }); const [filterMileageRange, setFilterMileageRange] = useState({ min: '', max: '' });
const [appliedMileageRange, setAppliedMileageRange] = useState({ min: '', max: '' });
const [vehicles, setVehicles] = useState<MonitoringVehicle[]>([]); const [vehicles, setVehicles] = useState<MonitoringVehicle[]>([]);
const [stats, setStats] = useState<MonitoringStats>({ totalToday: 0, totalAll: 0, onlineCount: 0, vehicleCount: 0 }); const [stats, setStats] = useState<MonitoringStats>({ totalToday: 0, totalAll: 0, onlineCount: 0, vehicleCount: 0 });
@@ -132,6 +133,8 @@ export default function MonitoringView() {
dept: filterDept !== 'All' ? filterDept : undefined, dept: filterDept !== 'All' ? filterDept : undefined,
project: filterProject !== 'All' ? filterProject : undefined, project: filterProject !== 'All' ? filterProject : undefined,
entity: filterEntity !== 'All' ? filterEntity : undefined, entity: filterEntity !== 'All' ? filterEntity : undefined,
mileageMin: appliedMileageRange.min || undefined,
mileageMax: appliedMileageRange.max || undefined,
}).then(d => { }).then(d => {
setVehicles(d.vehicles); setVehicles(d.vehicles);
setStats(d.stats); setStats(d.stats);
@@ -140,7 +143,7 @@ export default function MonitoringView() {
setPage(1); setPage(1);
setHasMore(d.page < d.totalPages); setHasMore(d.page < d.totalPages);
}).catch(() => {}); }).catch(() => {});
}, [sortBy, sortOrder, searchTerm, filterDept, filterProject, filterEntity]); }, [sortBy, sortOrder, searchTerm, filterDept, filterProject, filterEntity, appliedMileageRange]);
// 加载更多 // 加载更多
const loadMore = useCallback(() => { const loadMore = useCallback(() => {
@@ -156,12 +159,14 @@ export default function MonitoringView() {
dept: filterDept !== 'All' ? filterDept : undefined, dept: filterDept !== 'All' ? filterDept : undefined,
project: filterProject !== 'All' ? filterProject : undefined, project: filterProject !== 'All' ? filterProject : undefined,
entity: filterEntity !== 'All' ? filterEntity : undefined, entity: filterEntity !== 'All' ? filterEntity : undefined,
mileageMin: appliedMileageRange.min || undefined,
mileageMax: appliedMileageRange.max || undefined,
}).then(d => { }).then(d => {
setVehicles(prev => [...prev, ...d.vehicles]); setVehicles(prev => [...prev, ...d.vehicles]);
setPage(nextPage); setPage(nextPage);
setHasMore(nextPage < d.totalPages); setHasMore(nextPage < d.totalPages);
}).catch(() => {}).finally(() => setLoadingMore(false)); }).catch(() => {}).finally(() => setLoadingMore(false));
}, [sortBy, sortOrder, searchTerm, filterDept, filterProject, filterEntity, page, loadingMore, hasMore]); }, [sortBy, sortOrder, searchTerm, filterDept, filterProject, filterEntity, appliedMileageRange, page, loadingMore, hasMore]);
// 筛选/排序变化时重新加载 // 筛选/排序变化时重新加载
useEffect(() => { useEffect(() => {
@@ -684,13 +689,17 @@ export default function MonitoringView() {
setFilterEntity('All'); setFilterEntity('All');
setFilterRegionCode('All'); setFilterRegionCode('All');
setFilterMileageRange({ min: '', max: '' }); setFilterMileageRange({ min: '', max: '' });
setAppliedMileageRange({ min: '', max: '' });
}} }}
className="text-[10px] font-bold text-slate-400 hover:text-slate-600" className="text-[10px] font-bold text-slate-400 hover:text-slate-600"
> >
</button> </button>
<button <button
onClick={() => setIsFilterOpen(false)} onClick={() => {
setAppliedMileageRange({ ...filterMileageRange });
setIsFilterOpen(false);
}}
className="bg-blue-600 text-white px-6 py-2 rounded-xl text-xs font-bold shadow-lg shadow-blue-100" className="bg-blue-600 text-white px-6 py-2 rounded-xl text-xs font-bold shadow-lg shadow-blue-100"
> >

View File

@@ -18,6 +18,8 @@ export async function fetchMonitoring(params?: {
customer?: string; customer?: string;
project?: string; project?: string;
entity?: string; entity?: string;
mileageMin?: string;
mileageMax?: string;
}): Promise<MonitoringData> { }): Promise<MonitoringData> {
const query = new URLSearchParams(); const query = new URLSearchParams();
if (params?.sortBy) query.set('sortBy', params.sortBy); if (params?.sortBy) query.set('sortBy', params.sortBy);
@@ -29,6 +31,8 @@ export async function fetchMonitoring(params?: {
if (params?.customer) query.set('customer', params.customer); if (params?.customer) query.set('customer', params.customer);
if (params?.project) query.set('project', params.project); if (params?.project) query.set('project', params.project);
if (params?.entity) query.set('entity', params.entity); if (params?.entity) query.set('entity', params.entity);
if (params?.mileageMin) query.set('mileageMin', params.mileageMin);
if (params?.mileageMax) query.set('mileageMax', params.mileageMax);
const qs = query.toString(); const qs = query.toString();
return fetchJson<MonitoringData>(`${BASE}/monitoring${qs ? `?${qs}` : ''}`); return fetchJson<MonitoringData>(`${BASE}/monitoring${qs ? `?${qs}` : ''}`);
} }

View File

@@ -154,6 +154,8 @@ app.get('/monitoring', (c) => {
const customer = c.req.query('customer') || ''; const customer = c.req.query('customer') || '';
const project = c.req.query('project') || ''; const project = c.req.query('project') || '';
const entity = c.req.query('entity') || ''; const entity = c.req.query('entity') || '';
const mileageMin = c.req.query('mileageMin') || '';
const mileageMax = c.req.query('mileageMax') || '';
let vehicles = monitoringCache.vehicles; let vehicles = monitoringCache.vehicles;
@@ -170,6 +172,8 @@ app.get('/monitoring', (c) => {
if (customer) vehicles = vehicles.filter(v => v.customer === customer); if (customer) vehicles = vehicles.filter(v => v.customer === customer);
if (project) vehicles = vehicles.filter(v => v.project === project); if (project) vehicles = vehicles.filter(v => v.project === project);
if (entity) vehicles = vehicles.filter(v => v.entity === entity); if (entity) vehicles = vehicles.filter(v => v.entity === entity);
if (mileageMin) vehicles = vehicles.filter(v => v.dailyKm >= Number(mileageMin));
if (mileageMax) vehicles = vehicles.filter(v => v.dailyKm <= Number(mileageMax));
const total = vehicles.length; const total = vehicles.length;