说明文字
This commit is contained in:
parent
d72b18f713
commit
539c425a89
2
App.tsx
2
App.tsx
@ -55,7 +55,7 @@ export default function App() {
|
||||
<Stack.Screen
|
||||
name="Info"
|
||||
component={InfoScreen}
|
||||
options={{ title: "设备信息" }}
|
||||
options={{ title: "设备详情" }}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="Dfu"
|
||||
|
||||
@ -122,7 +122,7 @@ export default function DfuScreen({ route, navigation }: Props) {
|
||||
return (
|
||||
<View style={{ flex: 1, padding: 20 }}>
|
||||
<View style={styles.row}>
|
||||
<Text style={{ fontSize: 18 }}>蓝牙名称: {name}</Text>
|
||||
<Text style={{ fontSize: 16 }}>蓝牙名称: {name}</Text>
|
||||
</View>
|
||||
<View style={styles.row}>
|
||||
<Text style={{ fontSize: 16 }}>最新版本: {latestVersion}</Text>
|
||||
|
||||
@ -49,6 +49,11 @@ export default function InfoScreen({ route, navigation }: Props) {
|
||||
const { peripheral } = route.params;
|
||||
const deviceKey = peripheral.address || peripheral.systemId;
|
||||
|
||||
const [power, setPower] = useState<number>(0);
|
||||
const [cadence, setCadence] = useState<number>(0);
|
||||
const [leftbalance, setLeftBalance] = useState<number>(0);
|
||||
const [rightbalance, setRightBalance] = useState<number>(0);
|
||||
|
||||
const [isConnected, setIsConnected] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [serial, setSerial] = useState("读取中...");
|
||||
@ -56,7 +61,7 @@ export default function InfoScreen({ route, navigation }: Props) {
|
||||
const [hardware, setHardware] = useState("读取中...");
|
||||
const [battery, setBattery] = useState("读取中...");
|
||||
const [powerTrim, setPowerTrim] = useState("读取中");
|
||||
const [inputTrim, setInputTrim] = useState("100");
|
||||
const [inputTrim, setInputTrim] = useState("");
|
||||
|
||||
const [readSuccessToast, setReadSuccessToast] = useState(false); // ✅ 读取成功提示
|
||||
const [powerTrimLoading, setPowerTrimLoading] = useState(false); // 正在写入功率微调
|
||||
@ -69,6 +74,13 @@ export default function InfoScreen({ route, navigation }: Props) {
|
||||
const prevConnectedRef = useRef(isConnected);
|
||||
const isActiveRef = useRef(true);
|
||||
|
||||
//增加校准按钮相关状态
|
||||
const [calibrating, setCalibrating] = useState<boolean>(false);
|
||||
const [calibrationSuccess, setCalibrationSuccess] = useState<boolean>(false);
|
||||
const [calibrationValue, setCalibrationValue] = useState<string>("");
|
||||
const calibrationTimeoutRef = useRef<number | null>(null);
|
||||
const isCalibratingRef = useRef<boolean>(false);
|
||||
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
// 页面获得焦点
|
||||
@ -84,7 +96,7 @@ export default function InfoScreen({ route, navigation }: Props) {
|
||||
// ========== 监听连接状态变化,断开时提示重新连接 ==========
|
||||
useEffect(() => {
|
||||
if (prevConnectedRef.current && !isConnected && isActiveRef.current) {
|
||||
Alert.alert("提示", "请重新连接设备", [
|
||||
Alert.alert("提示", "设备已断开,请重新连接设备", [
|
||||
{ text: "确定", onPress: () => navigation.goBack() },
|
||||
]);
|
||||
}
|
||||
@ -121,7 +133,7 @@ export default function InfoScreen({ route, navigation }: Props) {
|
||||
return unsubscribe;
|
||||
}, [navigation, peripheral]);
|
||||
|
||||
// ========== BLE notify 订阅 ==========
|
||||
// ========== BLE notify 订阅FFF3 ==========
|
||||
useEffect(() => {
|
||||
const connectionHandler = async (ev: {
|
||||
peripheral: ScannedPeripheral;
|
||||
@ -151,13 +163,17 @@ export default function InfoScreen({ route, navigation }: Props) {
|
||||
try {
|
||||
const raw = (notifyEv as any).value;
|
||||
if (!raw) return;
|
||||
const arr =
|
||||
raw instanceof Uint8Array
|
||||
? Array.from(raw)
|
||||
: Array.from(new Uint8Array(raw));
|
||||
if (arr[0] === 0x02 && arr.length >= 2) {
|
||||
setPowerTrim(arr[1].toString());
|
||||
setInputTrim(arr[1].toString());
|
||||
const byteArray = raw instanceof Uint8Array
|
||||
? raw
|
||||
: new Uint8Array(raw);
|
||||
if (byteArray[0] === 0x02 && byteArray.length >= 2) {
|
||||
// 功率微调数据
|
||||
setPowerTrim(byteArray[1].toString());
|
||||
//setInputTrim(byteArray[1].toString());
|
||||
}
|
||||
else if (byteArray[0] === 0x05 && byteArray.length >= 3) {
|
||||
// 校准响应数据 (05XXXX格式)
|
||||
handleFFF3Response(byteArray);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn("notify parse error", err);
|
||||
@ -172,6 +188,8 @@ export default function InfoScreen({ route, navigation }: Props) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
Central.addListener("peripheralConnectionStatus", connectionHandler);
|
||||
return () => {
|
||||
Central.removeListener("peripheralConnectionStatus", connectionHandler);
|
||||
@ -249,11 +267,182 @@ export default function InfoScreen({ route, navigation }: Props) {
|
||||
})();
|
||||
}, [peripheral]);
|
||||
|
||||
|
||||
|
||||
|
||||
// ========== 订阅 1818 服务的 2A63 特性 (通知) ==========
|
||||
useEffect(() => {
|
||||
const subscribeToPowerData = async () => {
|
||||
try {
|
||||
// 确保设备已经连接
|
||||
if (!isConnected) return;
|
||||
|
||||
console.log("✅ 订阅 2A63 特性通知...");
|
||||
|
||||
// 先取消之前的订阅(防止重复订阅)
|
||||
await Central.unsubscribeCharacteristic(
|
||||
peripheral,
|
||||
fullUUID("1818"),
|
||||
fullUUID("2a63")
|
||||
).catch(() => {});
|
||||
|
||||
// 订阅 2A63 特性通知
|
||||
await Central.subscribeCharacteristic(
|
||||
peripheral,
|
||||
fullUUID("1818"),
|
||||
fullUUID("2a63"),
|
||||
(notifyEv) => {
|
||||
try {
|
||||
const raw = notifyEv.value;
|
||||
if (raw) {
|
||||
// 将 ArrayBuffer 转换为字节数组
|
||||
const byteArray = new Uint8Array(raw);
|
||||
|
||||
// 解析数据
|
||||
parseData(byteArray);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn("❌ 处理通知数据失败", err);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
console.log("✅ 已订阅 2A63 特性通知");
|
||||
} catch (err) {
|
||||
console.warn("❌ 订阅 2A63 特性失败", err);
|
||||
}
|
||||
};
|
||||
|
||||
// 只在设备已连接时进行订阅
|
||||
if (peripheral && isConnected) {
|
||||
subscribeToPowerData();
|
||||
}
|
||||
|
||||
// 清理订阅(当组件卸载或者连接状态变化时)
|
||||
return () => {
|
||||
if (peripheral && isConnected) {
|
||||
Central.unsubscribeCharacteristic(peripheral, fullUUID("1818"), fullUUID("2a63")).catch(() => {});
|
||||
}
|
||||
};
|
||||
}, [peripheral, isConnected]);
|
||||
|
||||
const cadenceStateRef = useRef({
|
||||
lastCadenceCount: 0, // 上一次的踏频翻转次数,用于计算差值
|
||||
lastCadenceTimestamp: 0, // 上一次的踏频时间戳(设备时间),用于计算差值
|
||||
lastCadenceChangedTime: 0, // 最后一次踏频变化的时间(本地时间),用于检测超时
|
||||
});
|
||||
|
||||
const parseData = (byteArray: Uint8Array) => {
|
||||
// 当前时间(用于超时检测)
|
||||
const currentTime = Date.now();
|
||||
// ========== 1. 解析功率 ==========
|
||||
// 字节2-3:功率值(小端序)
|
||||
const powerValue = (byteArray[3] << 8) | byteArray[2];
|
||||
setPower(powerValue);
|
||||
|
||||
// ========== 3. 解析踏频 ==========
|
||||
// 字节5-6:踏频翻转次数(小端序)
|
||||
const cadenceCount = (byteArray[6] << 8) | byteArray[5];
|
||||
|
||||
// 字节7-8:踏频时间戳(小端序)
|
||||
const timestamp = (byteArray[8] << 8) | byteArray[7];
|
||||
|
||||
// 获取上一次的状态
|
||||
const lastState = cadenceStateRef.current;
|
||||
|
||||
// 检测踏频翻转次数是否有变化
|
||||
const hasCadenceChanged = cadenceCount !== lastState.lastCadenceCount;
|
||||
|
||||
if (hasCadenceChanged) {
|
||||
// 踏频有变化,更新变化时间戳
|
||||
cadenceStateRef.current.lastCadenceChangedTime = currentTime;
|
||||
}
|
||||
|
||||
// 检查是否超时(3秒无变化)
|
||||
if (lastState.lastCadenceChangedTime > 0 &&
|
||||
currentTime - lastState.lastCadenceChangedTime > 3000) {
|
||||
//setPower("0 W");
|
||||
setCadence(0);
|
||||
setLeftBalance(0);
|
||||
setRightBalance(0);
|
||||
cadenceStateRef.current = {
|
||||
lastCadenceCount: 0,
|
||||
lastCadenceTimestamp: 0,
|
||||
lastCadenceChangedTime: 0,
|
||||
};
|
||||
return; // 超时后直接返回,不再计算踏频
|
||||
}
|
||||
|
||||
// 如果是第一次收到踏频数据,只记录不计算
|
||||
if (lastState.lastCadenceTimestamp === 0) {
|
||||
cadenceStateRef.current = {
|
||||
lastCadenceCount: cadenceCount,
|
||||
lastCadenceTimestamp: timestamp,
|
||||
lastCadenceChangedTime: hasCadenceChanged ? currentTime : 0,
|
||||
};
|
||||
setCadence(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算踏频RPM(只在踏频有变化时计算)
|
||||
if (hasCadenceChanged) {
|
||||
// 计算翻转次数差(处理16位计数器翻转)
|
||||
let revDiff = cadenceCount - lastState.lastCadenceCount;
|
||||
if (revDiff < 0) {
|
||||
revDiff += 65536; // 16位计数器最大值65535
|
||||
}
|
||||
|
||||
// 计算时间差(处理16位计数器翻转)
|
||||
let timeDiff = timestamp - lastState.lastCadenceTimestamp;
|
||||
if (timeDiff < 0) {
|
||||
timeDiff += 65536; // 16位计数器最大值65535
|
||||
}
|
||||
|
||||
// 计算踏频
|
||||
if (timeDiff > 0 && revDiff > 0) {
|
||||
// 假设时间单位是1/1024秒(蓝牙设备常用)
|
||||
const timeInSeconds = timeDiff / 1024.0;
|
||||
|
||||
// RPM = (圈数 / 时间(秒)) * 60
|
||||
const cadenceRPM = (revDiff / timeInSeconds) * 60;
|
||||
|
||||
// 限制合理范围
|
||||
if (cadenceRPM > 10 && cadenceRPM < 250) {
|
||||
setCadence(Math.round(cadenceRPM));
|
||||
} else {
|
||||
setCadence(0);
|
||||
}
|
||||
} else {
|
||||
// 如果没有翻转,踏频为0
|
||||
setCadence(0);
|
||||
}
|
||||
|
||||
// ========== 解析左平衡 ==========
|
||||
// 字节4:左平衡值,单位0.5%
|
||||
const leftBalanceValue = byteArray[4];
|
||||
const leftBalancePercent = Math.round(leftBalanceValue * 0.5 * 10) / 10;
|
||||
setLeftBalance(leftBalancePercent);
|
||||
// 计算右平衡:100% - 左平衡百分比
|
||||
const rightBalancePercent = Math.round((100 - leftBalancePercent) * 10) / 10;
|
||||
setRightBalance(rightBalancePercent);
|
||||
|
||||
// 更新踏频计算状态
|
||||
cadenceStateRef.current = {
|
||||
...cadenceStateRef.current,
|
||||
lastCadenceCount: cadenceCount,
|
||||
lastCadenceTimestamp: timestamp,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// ========== 写入功率微调 ==========
|
||||
const updatePowerTrim = async () => {
|
||||
const val = parseInt(inputTrim);
|
||||
if (isNaN(val) || val < 50 || val > 200) {
|
||||
Alert.alert("提示", "请输入有效数字(50~200)");
|
||||
Alert.alert("提示", "功率微调可调整功率计的高低偏差,默认值100%。可调整的范围是50%-200%。请输入50至200的纯数字,不需要包含%符号。输入后点击下方按钮更新进功率计设备。");
|
||||
return;
|
||||
}
|
||||
if (val === Number(powerTrim)) {
|
||||
@ -295,40 +484,215 @@ export default function InfoScreen({ route, navigation }: Props) {
|
||||
}
|
||||
};
|
||||
|
||||
// ========== 校准按钮逻辑 ==========
|
||||
const handleCalibration = async () => {
|
||||
if (!isConnected) {
|
||||
Alert.alert("提示", "设备未连接");
|
||||
return;
|
||||
}
|
||||
|
||||
if (calibrating) {
|
||||
return; // 正在校准中,不重复点击
|
||||
}
|
||||
|
||||
try {
|
||||
setCalibrating(true);
|
||||
isCalibratingRef.current = true;
|
||||
setCalibrationSuccess(false);
|
||||
setCalibrationValue("");
|
||||
|
||||
console.log("🔧 开始校准,向FFF2写入05");
|
||||
|
||||
// 向FFF2写入05
|
||||
await Central.writeCharacteristic(
|
||||
peripheral,
|
||||
fullUUID("FFF1"), // 服务UUID
|
||||
fullUUID("FFF2"), // 写入特征UUID
|
||||
new Uint8Array([0x05]).buffer,
|
||||
{ withoutResponse: false }
|
||||
);
|
||||
|
||||
console.log("✅ 已发送校准命令,等待响应...");
|
||||
|
||||
// 设置5秒超时
|
||||
calibrationTimeoutRef.current = setTimeout(() => {
|
||||
if (isCalibratingRef.current) {
|
||||
console.log("❌ 校准超时,未收到响应");
|
||||
Alert.alert("校准错误", "设备未响应,请重试");
|
||||
setCalibrating(false);
|
||||
isCalibratingRef.current = false;
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
} catch (err) {
|
||||
console.warn("❌ 发送校准命令失败", err);
|
||||
Alert.alert("错误", "发送校准命令失败");
|
||||
setCalibrating(false);
|
||||
isCalibratingRef.current = false;
|
||||
|
||||
if (calibrationTimeoutRef.current) {
|
||||
clearTimeout(calibrationTimeoutRef.current);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleFFF3Response = (byteArray: Uint8Array) => {
|
||||
// 如果不是正在校准中,不处理
|
||||
if (!isCalibratingRef.current) return;
|
||||
|
||||
// 清除超时定时器
|
||||
if (calibrationTimeoutRef.current) {
|
||||
clearTimeout(calibrationTimeoutRef.current);
|
||||
calibrationTimeoutRef.current = null;
|
||||
}
|
||||
|
||||
// 检查响应数据格式:05XXXX (05开头,后面至少2个字节)
|
||||
// 假设响应是05 + 2字节的小端序数值
|
||||
if (byteArray[0] === 0x05 && byteArray.length >= 3) {
|
||||
// 解析XXXX(小端序):低位在前,高位在后
|
||||
// byteArray[1] 是低位字节,byteArray[2] 是高位字节
|
||||
const value = Math.round (((byteArray[2] << 8) | byteArray[1])/10 ) ; //除以10发送出来 不然数据容易乱跳 和码表端处理保持一致
|
||||
console.log(`✅ 收到校准响应,值: ${value}`);
|
||||
|
||||
// 更新状态
|
||||
setCalibrationValue(value.toString());
|
||||
setCalibrationSuccess(true);
|
||||
|
||||
// 显示成功弹框
|
||||
Alert.alert(
|
||||
"校准成功",
|
||||
`校准值: ${value}`,
|
||||
[
|
||||
{
|
||||
text: "确定",
|
||||
onPress: () => {
|
||||
setCalibrating(false);
|
||||
isCalibratingRef.current = false;
|
||||
setCalibrationSuccess(false);
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
} else {
|
||||
console.warn("❌ 校准响应格式错误", byteArray);
|
||||
Alert.alert("校准错误", "设备返回数据格式错误");
|
||||
setCalibrating(false);
|
||||
isCalibratingRef.current = false;
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
// 清理校准超时定时器
|
||||
if (calibrationTimeoutRef.current) {
|
||||
clearTimeout(calibrationTimeoutRef.current);
|
||||
calibrationTimeoutRef.current = null;
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
||||
// ========== UI ==========
|
||||
return (
|
||||
<ScrollView contentContainerStyle={{ padding: 20, gap: 8 }}>
|
||||
|
||||
<View style={styles.row}>
|
||||
<Text>蓝牙名称: {peripheral.name}</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.row}>
|
||||
<Text>ID号: {serial}</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.row}>
|
||||
<Text>固件版本: {firmware}</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.row}>
|
||||
<Text>电量: {battery}</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.row}>
|
||||
<Text>连接状态: {isConnected ? "已连接" : "未连接"}</Text>
|
||||
</View>
|
||||
|
||||
<View style={{ marginTop: 20 }}>
|
||||
<Text>功率微调: {powerTrim}%</Text>
|
||||
{/* ====== 实时数据三卡片 ====== */}
|
||||
<View style={styles.realtimeContainer}>
|
||||
{/* 功率 */}
|
||||
<View style={styles.realtimeCard}>
|
||||
<Icon name="flash" size={22} color="#E7141E" />
|
||||
<Text style={styles.realtimeLabel}>功率/W</Text>
|
||||
<Text style={styles.realtimeValue}>{power}</Text>
|
||||
</View>
|
||||
|
||||
{/* 踏频 */}
|
||||
<View style={styles.realtimeCard}>
|
||||
<Icon name="sync" size={22} color="#E7141E" />
|
||||
<Text style={styles.realtimeLabel}>踏频/RPM</Text>
|
||||
<Text style={styles.realtimeValue}>{cadence}</Text>
|
||||
</View>
|
||||
|
||||
{/* 左右平衡 */}
|
||||
<View style={styles.realtimeCard}>
|
||||
<Text style={styles.balanceHeader}>L / R</Text>
|
||||
<Text style={styles.realtimeLabel}>左右平衡/%</Text>
|
||||
<Text style={styles.realtimeValue}>
|
||||
{leftbalance}/{rightbalance}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
|
||||
|
||||
{/* ========== 功率微调卡片部分 ========== */}
|
||||
<View style={styles.cardContainer}>
|
||||
<View style={styles.cardTitle}>
|
||||
<Text style={[styles.cardTitleText, { textAlign: 'center' }]}>功率微调设置</Text>
|
||||
</View>
|
||||
|
||||
<View style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
marginBottom: 0,
|
||||
paddingHorizontal: 10
|
||||
}}>
|
||||
<Text style={{ marginTop: 10,flex: 1, marginRight: 10 }}>当前微调: {powerTrim}%</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
style={[styles.input, { flex: 1 , marginTop: 10 }]}
|
||||
value={inputTrim}
|
||||
onChangeText={setInputTrim}
|
||||
keyboardType="numeric"
|
||||
onEndEditing={updatePowerTrim}
|
||||
placeholder="输入50-200"
|
||||
/>
|
||||
<Pressable onPress={updatePowerTrim} style={styles.pressable} disabled={isLoading || powerTrimLoading}>
|
||||
<Text style={{ color: "white" }}>更新功率微调</Text>
|
||||
</View>
|
||||
|
||||
<Pressable
|
||||
onPress={updatePowerTrim}
|
||||
style={styles.pressable}
|
||||
disabled={isLoading || powerTrimLoading}
|
||||
>
|
||||
<Text style={{ color: "white" }}>更新数值</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
|
||||
<View style={{ marginTop: 30 }}>
|
||||
{/* ========== 新增校准按钮 ========== */}
|
||||
<View style={{ marginTop: 0 }}>
|
||||
<Pressable
|
||||
onPress={handleCalibration}
|
||||
style={[styles.pressable, calibrating && styles.disabledButton]}
|
||||
disabled={calibrating || !isConnected}
|
||||
>
|
||||
<Text style={{ color: "white" }}>
|
||||
{calibrating ? "校准中...等待设备反应" : "校准归零"}
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
|
||||
|
||||
|
||||
<View style={{ marginTop: 0 }}>
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
if (!isConnected) {
|
||||
@ -343,7 +707,6 @@ export default function InfoScreen({ route, navigation }: Props) {
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
// 蓝牙已连接,正常跳转 DFU
|
||||
navigation.navigate("Dfu", {
|
||||
deviceId: deviceKey,
|
||||
@ -354,13 +717,15 @@ export default function InfoScreen({ route, navigation }: Props) {
|
||||
style={styles.pressable}
|
||||
disabled={isLoading || powerTrimLoading} // ❌ 禁用点击
|
||||
>
|
||||
<Text style={{ color: "white" }}>升级固件</Text>
|
||||
<Text style={{ color: "white" }}>固件升级</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
|
||||
|
||||
|
||||
{isLoading && (
|
||||
<View style={{ marginVertical: 60, alignItems: "center" }}>
|
||||
<ActivityIndicator size={80} color="#E7141E" />
|
||||
<ActivityIndicator size={30} color="#E7141E" />
|
||||
<Text style={{ marginTop: 10, fontSize: 16 }}>正在读取信息...</Text>
|
||||
</View>
|
||||
)}
|
||||
@ -368,7 +733,7 @@ export default function InfoScreen({ route, navigation }: Props) {
|
||||
{/* ✅ 读取成功提示,固定在页面底部 */}
|
||||
{readSuccessToast && (
|
||||
<View style={{ marginVertical: 60, alignItems: "center" }}>
|
||||
<Icon name="check-circle" size={60} color="#E7141E" />
|
||||
<Icon name="check-circle" size={30} color="#E7141E" />
|
||||
<Text style={{ marginTop: 10, fontSize: 16 }}>读取成功!</Text>
|
||||
</View>
|
||||
)}
|
||||
@ -376,7 +741,7 @@ export default function InfoScreen({ route, navigation }: Props) {
|
||||
{/* 正在写入功率微调 */}
|
||||
{powerTrimLoading && (
|
||||
<View style={{ marginVertical: 60, alignItems: "center" }}>
|
||||
<ActivityIndicator size={60} color="#E7141E" />
|
||||
<ActivityIndicator size={30} color="#E7141E" />
|
||||
<Text style={{ marginTop: 10, fontSize: 16 }}>正在写入功率微调...</Text>
|
||||
</View>
|
||||
)}
|
||||
@ -384,7 +749,7 @@ export default function InfoScreen({ route, navigation }: Props) {
|
||||
{/* 功率微调写入成功 */}
|
||||
{powerTrimSuccessToast && (
|
||||
<View style={{ marginVertical: 60, alignItems: "center" }}>
|
||||
<Icon name="check-circle" size={60} color="#E7141E" />
|
||||
<Icon name="check-circle" size={30} color="#E7141E" />
|
||||
<Text style={{ marginTop: 10, fontSize: 16 }}>功率微调更新成功!</Text>
|
||||
</View>
|
||||
)}
|
||||
@ -397,7 +762,7 @@ const styles = StyleSheet.create({
|
||||
row: {
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: "#E7141E",
|
||||
paddingBottom: 4, // 横线和文字保持一定间距
|
||||
paddingBottom: 3, // 横线和文字保持一定间距
|
||||
marginBottom: 8, // 行间距
|
||||
},
|
||||
input: {
|
||||
@ -414,4 +779,79 @@ const styles = StyleSheet.create({
|
||||
borderRadius: 6,
|
||||
alignItems: "center",
|
||||
},
|
||||
disabledButton: {
|
||||
backgroundColor: "#999", // 禁用时的颜色
|
||||
opacity: 0.6,
|
||||
},
|
||||
|
||||
cardContainer: {
|
||||
borderWidth: 1,
|
||||
borderColor: "#ddd",
|
||||
borderRadius: 10,
|
||||
marginTop: 10,
|
||||
backgroundColor: "#fff",
|
||||
overflow: 'hidden', // 确保圆角效果完整
|
||||
shadowColor: "#000",
|
||||
shadowOffset: { width: 0, height: 1 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 2,
|
||||
elevation: 2, // Android阴影
|
||||
},
|
||||
cardTitle: {
|
||||
backgroundColor: "#f5f5f5",
|
||||
paddingVertical: 8,
|
||||
paddingHorizontal: 15,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: "#eee",
|
||||
},
|
||||
cardTitleText: {
|
||||
fontWeight: 'bold',
|
||||
color: "#333",
|
||||
},
|
||||
|
||||
realtimeContainer: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
marginVertical: 10,
|
||||
},
|
||||
|
||||
realtimeCard: {
|
||||
flex: 1,
|
||||
marginHorizontal: 4,
|
||||
paddingVertical: 12,
|
||||
borderRadius: 10,
|
||||
backgroundColor: "#fff",
|
||||
alignItems: "center",
|
||||
|
||||
borderWidth: 1,
|
||||
borderColor: "#E7141E",
|
||||
|
||||
shadowColor: "#000",
|
||||
shadowOffset: { width: 0, height: 1 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 2,
|
||||
elevation: 2,
|
||||
},
|
||||
|
||||
realtimeLabel: {
|
||||
marginTop: 6,
|
||||
fontSize: 14,
|
||||
color: "#666",
|
||||
},
|
||||
|
||||
realtimeValue: {
|
||||
marginTop: 4,
|
||||
fontSize: 20,
|
||||
fontWeight: "bold",
|
||||
color: "#000",
|
||||
},
|
||||
|
||||
balanceHeader: {
|
||||
fontSize: 16,
|
||||
fontWeight: "bold",
|
||||
color: "#E7141E",
|
||||
},
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user