import React, { useState } from 'react'; import { View, Text, FlatList, TouchableOpacity, StyleSheet, Alert, ActivityIndicator, } from 'react-native'; import { router } from 'expo-router'; import { useDataStore } from '../../src/stores/dataStore'; import { exportCsv, shareFile } from '../../src/utils/export'; import { formatUtc, formatCoord, formatUV } from '../../src/utils/format'; import type { MeasurementFrame } from '../../src/protocol/types'; export default function RecordsScreen() { const { history, sessionId, clearHistory } = useDataStore(); const [exporting, setExporting] = useState(false); const handleExportAll = async () => { if (history.length === 0) { Alert.alert('无数据', '当前会话没有采集记录'); return; } setExporting(true); try { const path = await exportCsv(history, sessionId); await shareFile(path); } catch (e: any) { Alert.alert('导出失败', e.message); } finally { setExporting(false); } }; const handleClear = () => { Alert.alert('清空记录', '确定清空当前会话的所有记录?', [ { text: '取消', style: 'cancel' }, { text: '清空', style: 'destructive', onPress: clearHistory }, ]); }; const renderItem = ({ item }: { item: MeasurementFrame }) => { const m = item.meta; const peakUV = item.adcUV[0] ? item.adcUV[0].reduce((mx, v) => Math.max(mx, Math.abs(v)), 0) : 0; return ( #{item.frameId} {m ? formatUtc(m.utc) : '--'} {m && ( <> {formatCoord(m.latitude, false)} {formatCoord(m.longitude, true)} 叠加 {item.accNum}次 增益 ×{item.gain} CH1峰值 {formatUV(peakUV)} 0 ? '#1a4a1a' : '#2a1a1a' }]}> 0 ? '#44cc44' : '#884444', fontSize: 9 }}> GPS {m.gpsStatus > 0 ? '✓' : '✗'} )} ); }; return ( {/* Toolbar */} 会话: {sessionId} {history.length} 测点 {exporting ? ( ) : ( 导出 CSV )} 清空 {history.length === 0 ? ( 暂无采集记录 在控制台开始采集后,数据将显示在这里 ) : ( String(item.frameId)} renderItem={renderItem} contentContainerStyle={styles.list} ItemSeparatorComponent={() => } /> )} ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#0d0d0d' }, toolbar: { flexDirection: 'row', alignItems: 'center', padding: 10, backgroundColor: '#111', borderBottomWidth: 1, borderBottomColor: '#2a2a2a', gap: 8, flexWrap: 'wrap', }, sessionText: { color: '#555', fontSize: 10, flex: 1 }, countText: { color: '#888', fontSize: 12, fontWeight: '600' }, toolbarBtns: { flexDirection: 'row', gap: 8 }, toolBtn: { paddingHorizontal: 12, paddingVertical: 6, borderRadius: 6 }, exportBtn: { backgroundColor: '#1a3a1a', borderWidth: 1, borderColor: '#2a5a2a' }, exportText: { color: '#44cc44', fontSize: 12, fontWeight: '600' }, clearBtn: { backgroundColor: '#3a1a1a', borderWidth: 1, borderColor: '#5a2a2a' }, clearText: { color: '#ff6666', fontSize: 12 }, btnDisabled: { opacity: 0.4 }, list: { padding: 10, gap: 8 }, item: { backgroundColor: '#181818', borderRadius: 8, padding: 10, borderWidth: 1, borderColor: '#2a2a2a', }, itemHeader: { flexDirection: 'row', justifyContent: 'space-between', marginBottom: 4 }, frameId: { color: '#4a9eff', fontSize: 12, fontWeight: '700', fontFamily: 'monospace' }, time: { color: '#666', fontSize: 10, fontFamily: 'monospace' }, coord: { color: '#888', fontSize: 10, marginBottom: 4 }, itemFooter: { flexDirection: 'row', alignItems: 'center', gap: 8, flexWrap: 'wrap' }, meta: { color: '#555', fontSize: 10 }, gpsIndicator: { borderRadius: 4, paddingHorizontal: 4, paddingVertical: 1 }, sep: { height: StyleSheet.hairlineWidth, backgroundColor: '#222' }, empty: { flex: 1, justifyContent: 'center', alignItems: 'center', gap: 8 }, emptyText: { color: '#444', fontSize: 16 }, emptyHint: { color: '#333', fontSize: 12 }, });