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 },
});