update:优化ota

This commit is contained in:
2026-09-24 15:16:14 +08:00
parent f8bf9fdb63
commit f4b37fba00
6 changed files with 200 additions and 303 deletions
@@ -99,7 +99,7 @@ export function useDeviceStatus({
const refreshDeviceDetails = async () => {
const deviceId = device.value.deviceId;
if (!deviceId) return;
if (!deviceId) return null;
const requestVersion = ++deviceDetailRequestVersion;
try {
@@ -111,13 +111,17 @@ export function useDeviceStatus({
requestVersion !== deviceDetailRequestVersion ||
device.value.deviceId !== deviceId
) {
return;
return null;
}
deviceDetails.value = {
...deviceDetails.value,
...detail,
deviceModelName: detail.deviceModelName ?? "",
latestVersion: detail.latestVersion ?? "",
needUpdate: detail.needUpdate ?? false,
forceUpdate: detail.forceUpdate ?? false,
version: detail.version ?? "",
bindTime: String(
detail.bindTime ?? deviceDetails.value.bindTime ?? ""
).trim(),
@@ -126,9 +130,11 @@ export function useDeviceStatus({
).trim(),
};
updateDeviceUsageDuration(detail.onlineDuration, deviceId);
return detail;
} catch (error) {
// 实时刷新失败时保留当前页面数据,等待下次通知或页面重新显示。
console.log("刷新设备详情失败", error);
return null;
}
};
@@ -143,6 +149,10 @@ export function useDeviceStatus({
let latestDevice = {
...currentDevice,
deviceModelName: "",
latestVersion: "",
needUpdate: false,
forceUpdate: false,
version: "",
bindTime: "",
qrCodeUrl: "",
};
+47 -112
View File
@@ -8,7 +8,6 @@ import ScreenHint from "@/components/ScreenHint.vue";
import ModalDialog from "@/components/ModalDialog.vue";
import OtaModal from "@/components/OtaModal.vue";
import {
getHardwareBoxVersionAPI,
laserAimAPI,
updateDeviceAliasAPI,
} from "@/apis";
@@ -19,7 +18,7 @@ import {
DEVICE_NAME_STORAGE_KEY,
useDeviceStatus,
} from "./composables/useDeviceStatus";
import { useOtaUpdate } from "@/composables/useOtaUpdate";
import { getOtaInfoFromDetail, useOtaUpdate } from "@/composables/useOtaUpdate";
const store = useStore();
const { updateDevice, updateDeviceUsageDuration, clearDevice } = store;
@@ -62,11 +61,8 @@ const showDeviceId = ref(false);
const latestVersionDialogVisible = ref(false);
const firmwareConfirmVisible = ref(false);
const wifiRequiredVisible = ref(false);
const otaNeedUpdate = ref(false);
const firmwareActionPending = ref(false);
const pendingOtaInfo = ref(null);
let otaCheckPromise = null;
let otaCheckRequestVersion = 0;
const {
updating: otaUpdating,
@@ -113,6 +109,12 @@ const wifiStatusText = computed(() => {
const bindingDateText = computed(() =>
formatBindingDate(deviceDetails.value.bindTime)
);
const otaNeedUpdate = computed(() => {
const info = getOtaInfoFromDetail(deviceDetails.value);
return isDeviceOnline.value &&
deviceDetails.value.deviceId === device.value.deviceId &&
info.needUpdate && !!info.versionNumber;
});
// 固件版本统一以大写 V 开头,避免接口返回格式不一致影响弹窗展示。
const formatFirmwareVersion = (value) => {
@@ -122,18 +124,12 @@ const formatFirmwareVersion = (value) => {
};
const firmwareConfirmContent = computed(() => {
const currentVersion = formatFirmwareVersion(deviceStatus.value.version);
const latestVersion = formatFirmwareVersion(
pendingOtaInfo.value?.versionNumber
);
const currentVersion = formatFirmwareVersion(pendingOtaInfo.value?.currentVersion);
const latestVersion = formatFirmwareVersion(pendingOtaInfo.value?.versionNumber);
if (currentVersion && latestVersion) {
return `当前固件版本为 ${currentVersion},发现新固件版本 ${latestVersion},是否立即更新固件?`;
}
if (latestVersion) {
return `发现新固件版本 ${latestVersion},是否立即更新固件?`;
}
return "发现新固件版本,是否立即更新固件?";
return latestVersion ? `发现新固件版本 ${latestVersion},是否立即更新固件?` : "是否立即更新固件?";
});
const deviceIdText = computed(() =>
@@ -272,84 +268,20 @@ const joinWifi = () => {
uni.navigateTo({ url: "/pages/device/ota-wifi" });
};
const clearOtaState = () => {
otaCheckRequestVersion += 1;
otaCheckPromise = null;
otaNeedUpdate.value = false;
};
const loadOtaVersionInfo = async () => {
if (otaCheckPromise) return otaCheckPromise;
const deviceId = device.value.deviceId;
if (!deviceId || !isDeviceOnline.value) return null;
const requestVersion = ++otaCheckRequestVersion;
const request = getHardwareBoxVersionAPI()
.then((versionInfo) => {
if (
requestVersion !== otaCheckRequestVersion ||
device.value.deviceId !== deviceId ||
!isDeviceOnline.value
) {
return null;
}
if (!versionInfo || typeof versionInfo !== "object") {
throw new Error("固件版本信息为空");
}
const needUpdate =
versionInfo.needUpdate === true || Number(versionInfo.needUpdate) === 1;
otaNeedUpdate.value = needUpdate;
return {
versionNumber: versionInfo.versionNumber || "",
resourceUrl: versionInfo.resourceUrl || "",
needUpdate,
};
})
.finally(() => {
if (otaCheckPromise === request) {
otaCheckPromise = null;
}
});
otaCheckPromise = request;
return request;
};
const refreshOtaUpdateState = async () => {
otaNeedUpdate.value = false;
if (!device.value.deviceId || !isDeviceOnline.value) {
clearOtaState();
return;
}
try {
await loadOtaVersionInfo();
} catch (error) {
clearOtaState();
console.log("检查固件更新失败", error);
}
const closeFirmwareConfirm = () => {
firmwareConfirmVisible.value = false;
};
const closeLatestVersionDialog = () => {
latestVersionDialogVisible.value = false;
};
const closeFirmwareConfirm = () => {
firmwareConfirmVisible.value = false;
};
const runFirmwareUpdate = () => {
const versionInfo = pendingOtaInfo.value;
if (!versionInfo) return;
const otaInfo = pendingOtaInfo.value;
if (!otaInfo || otaInfo.deviceId !== device.value.deviceId) return;
void startOtaUpdate({
versionNumber: versionInfo.versionNumber,
resourceUrl: versionInfo.resourceUrl,
onSuccess: () => {
otaNeedUpdate.value = false;
},
versionNumber: otaInfo.versionNumber,
onSuccess: () => void refreshDeviceDetails(),
});
};
@@ -367,42 +299,43 @@ const confirmFirmwareUpdate = () => {
};
const goWifiForFirmwareUpdate = () => {
const versionInfo = pendingOtaInfo.value;
if (!versionInfo) return;
const otaInfo = pendingOtaInfo.value;
if (!otaInfo || otaInfo.deviceId !== device.value.deviceId) return;
wifiRequiredVisible.value = false;
const query = [
"source=firmware-update",
`versionNumber=${encodeURIComponent(versionInfo.versionNumber)}`,
`resourceUrl=${encodeURIComponent(versionInfo.resourceUrl)}`,
].join("&");
uni.navigateTo({ url: `/pages/device/ota-wifi?${query}` });
const versionNumber = encodeURIComponent(otaInfo.versionNumber);
uni.navigateTo({ url: `/pages/device/ota-wifi?source=firmware-update&versionNumber=${versionNumber}` });
};
const handleOtaResultClose = () => {
closeOtaResult();
void refreshOtaUpdateState();
void refreshDeviceDetails();
};
const goFirmwareUpdate = async () => {
if (firmwareActionPending.value) return;
if (firmwareActionPending.value || otaUpdating.value) return;
if (!isDeviceOnline.value) {
uni.showToast({ title: "请先开启智能弓", icon: "none" });
return;
}
firmwareActionPending.value = true;
const deviceId = device.value.deviceId;
try {
const versionInfo = await loadOtaVersionInfo();
if (!versionInfo) return;
if (!versionInfo.needUpdate) {
const detail = await refreshDeviceDetails();
if (!detail || device.value.deviceId !== deviceId) {
uni.showToast({ title: "获取设备详情失败,请重试", icon: "none" });
return;
}
const otaInfo = getOtaInfoFromDetail(detail);
if (!otaInfo.needUpdate) {
latestVersionDialogVisible.value = true;
return;
}
pendingOtaInfo.value = versionInfo;
if (!otaInfo.versionNumber) {
uni.showToast({ title: "缺少固件目标版本,请重试", icon: "none" });
return;
}
pendingOtaInfo.value = { ...otaInfo, deviceId };
firmwareConfirmVisible.value = true;
} catch (error) {
uni.showToast({ title: "获取更新版本失败,请重试", icon: "none" });
} finally {
firmwareActionPending.value = false;
}
@@ -451,15 +384,20 @@ watch(
(isOnline, wasOnline) => {
if (isOnline && !wasOnline) {
void refreshDeviceDetails();
void refreshOtaUpdateState();
return;
}
if (!isOnline) {
clearOtaState();
} else if (!isOnline) {
firmwareConfirmVisible.value = false;
wifiRequiredVisible.value = false;
}
}
);
watch(() => device.value.deviceId, () => {
pendingOtaInfo.value = null;
latestVersionDialogVisible.value = false;
firmwareConfirmVisible.value = false;
wifiRequiredVisible.value = false;
});
onLoad((options = {}) => {
retryScanOnShow.value = options.retryScan === "1";
});
@@ -475,7 +413,6 @@ onUnmounted(() => {
onShow(async () => {
calibration.value = uni.getStorageSync("calibration");
await syncDeviceBinding();
void refreshOtaUpdateState();
if (retryScanOnShow.value) {
retryScanOnShow.value = false;
handleScan();
@@ -607,10 +544,7 @@ onShow(async () => {
</view>
<view class="action-label-wrap">
<text>固件更新</text>
<text
v-if="otaNeedUpdate"
class="action-badge action-badge--new"
>New</text>
<text v-if="otaNeedUpdate" class="action-badge action-badge--new">New</text>
</view>
</view>
<view class="action-item" @click="joinWifi">
@@ -724,6 +658,7 @@ onShow(async () => {
:content="firmwareConfirmContent"
cancelText="暂不更新"
confirmText="立即更新"
:showCancel="!pendingOtaInfo?.forceUpdate"
:onCancel="closeFirmwareConfirm"
:onConfirm="confirmFirmwareUpdate"
></ModalDialog>
+27 -32
View File
@@ -9,10 +9,10 @@ import useStore from "@/store";
import { capsuleHeight } from "@/util";
import {
connectDeviceWifiAPI,
getDeviceDetailAPI,
getDeviceWifiStatusAPI,
getHardwareBoxVersionAPI,
} from "@/apis";
import { useOtaUpdate } from "@/composables/useOtaUpdate";
import { getOtaInfoFromDetail, useOtaUpdate } from "@/composables/useOtaUpdate";
const STATES = {
SCANNING: "SCANNING",
@@ -23,7 +23,7 @@ const STATES = {
};
const isIOS = uni.getDeviceInfo().osName === "ios";
const { deviceStatus } = storeToRefs(useStore());
const { device, deviceStatus } = storeToRefs(useStore());
const currentState = ref(STATES.SCANNING);
const connectedWifi = ref(null);
const connectedWifiName = ref("");
@@ -45,10 +45,7 @@ const showPassword = ref(false);
// 刷新防抖标志:扫描进行中为 true,禁止重复点击;扫描结束(成功/失败)后重置为 false。
const isRefreshing = ref(false);
const fromFirmwareUpdate = ref(false);
const routeOtaInfo = ref({
versionNumber: "",
resourceUrl: "",
});
const routeOtaVersionNumber = ref("");
const countdownVisible = ref(false);
const countdownSeconds = ref(3);
const firmwareMessageVisible = ref(false);
@@ -395,37 +392,38 @@ const joinNetwork = () => {
submitDeviceWifiConfig({ ssid, password });
};
// 获取 OTA 更新版本信息,正常使用入口传参,缺失时再请求后端兜底。
const getOtaVersionInfo = async () => {
if (routeOtaInfo.value.versionNumber && routeOtaInfo.value.resourceUrl) {
return {
needUpdate: true,
versionNumber: routeOtaInfo.value.versionNumber,
resourceUrl: routeOtaInfo.value.resourceUrl,
};
}
return getHardwareBoxVersionAPI();
};
const startFirmwareUpdate = async () => {
if (!fromFirmwareUpdate.value || !connectedWifi.value || otaUpdating.value) return;
const deviceId = device.value.deviceId;
const wifi = connectedWifi.value;
if (!deviceId) return;
try {
const versionInfo = await getOtaVersionInfo();
if (!versionInfo?.needUpdate) {
const response = await getDeviceDetailAPI(deviceId);
const detail = response?.detail || response?.data?.detail;
if (!detail || device.value.deviceId !== deviceId) throw new Error("设备详情已失效");
const otaInfo = getOtaInfoFromDetail(detail);
if (!otaInfo.needUpdate) {
firmwareMessage.value = "当前已是最新版本";
firmwareMessageVisible.value = true;
return;
}
await startOtaUpdate({
versionNumber: versionInfo.versionNumber,
wifiSsid: connectedWifi.value.SSID,
wifiPassword: connectedWifi.value.password || "",
resourceUrl: versionInfo.resourceUrl,
});
if (!otaInfo.versionNumber) {
firmwareMessage.value = "缺少固件目标版本,请返回后重试";
firmwareMessageVisible.value = true;
return;
}
// WiFi 连接可能耗时较长,以更新前的最新设备详情为准。
routeOtaVersionNumber.value = otaInfo.versionNumber;
} catch (error) {
firmwareMessage.value = "获取更新版本失败,请重试";
firmwareMessage.value = "获取设备详情失败,请返回后重试";
firmwareMessageVisible.value = true;
return;
}
await startOtaUpdate({
versionNumber: routeOtaVersionNumber.value,
wifiSsid: wifi.SSID,
wifiPassword: wifi.password || "",
});
};
const clearFirmwareCountdown = () => {
@@ -466,10 +464,7 @@ const togglePasswordVisibility = () => {
// 页面加载时识别普通 WiFi 入口和固件更新入口。
onLoad((options = {}) => {
fromFirmwareUpdate.value = options.source === "firmware-update";
routeOtaInfo.value = {
versionNumber: decodeURIComponent(options.versionNumber || ""),
resourceUrl: decodeURIComponent(options.resourceUrl || ""),
};
routeOtaVersionNumber.value = decodeURIComponent(options.versionNumber || "");
});
// 页面挂载后启动 WiFi 扫描流程。