update:新增ota
This commit is contained in:
+181
-27
@@ -5,6 +5,7 @@ import Container from "@/components/Container.vue";
|
||||
import Header from "@/components/Header.vue";
|
||||
import ScreenHint from "@/components/ScreenHint.vue";
|
||||
import ModalDialog from "@/components/ModalDialog.vue";
|
||||
import OtaModal from "@/components/OtaModal.vue";
|
||||
import {
|
||||
getHardwareBoxVersionAPI,
|
||||
laserAimAPI,
|
||||
@@ -17,10 +18,12 @@ import {
|
||||
DEVICE_NAME_STORAGE_KEY,
|
||||
useDeviceStatus,
|
||||
} from "./composables/useDeviceStatus";
|
||||
import { useOtaUpdate } from "./composables/useOtaUpdate";
|
||||
|
||||
const store = useStore();
|
||||
const { updateDevice, clearDevice } = store;
|
||||
const { user, device, deviceStatus, online } = storeToRefs(store);
|
||||
const DEVICE_NAME_MAX_LENGTH = 10;
|
||||
|
||||
const formatBindingDate = (value) => {
|
||||
if (!value) return "--";
|
||||
@@ -56,11 +59,26 @@ const retryScanOnShow = ref(false);
|
||||
const calibration = ref(false);
|
||||
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,
|
||||
progress: otaProgress,
|
||||
phase: otaPhase,
|
||||
resultVisible: otaResultVisible,
|
||||
resultStatus: otaResultStatus,
|
||||
resultTitle: otaResultTitle,
|
||||
resultContent: otaResultContent,
|
||||
startUpdate: startOtaUpdate,
|
||||
closeResult: closeOtaResult,
|
||||
} = useOtaUpdate();
|
||||
|
||||
const {
|
||||
batteryText,
|
||||
deviceDetails,
|
||||
@@ -94,8 +112,8 @@ const bindingDateText = computed(() =>
|
||||
);
|
||||
|
||||
const deviceIdText = computed(() =>
|
||||
showDeviceId.value && device.value.deviceId
|
||||
? device.value.deviceId
|
||||
showDeviceId.value && device.value.deviceName
|
||||
? device.value.deviceName
|
||||
: maskedDeviceId.value
|
||||
);
|
||||
|
||||
@@ -107,9 +125,11 @@ const designDeviceStats = computed(() => [
|
||||
},
|
||||
{
|
||||
label: "剩余电量",
|
||||
value: batteryText.value === "暂无数据" || !isDeviceOnline.value
|
||||
? "--"
|
||||
: batteryText.value,
|
||||
value: !isDeviceOnline.value
|
||||
? "设备离线"
|
||||
: batteryText.value === "暂无数据"
|
||||
? "--"
|
||||
: batteryText.value,
|
||||
},
|
||||
{
|
||||
label: "累计使用",
|
||||
@@ -150,6 +170,14 @@ const closeNameEditor = () => {
|
||||
nameEditorVisible.value = false;
|
||||
};
|
||||
|
||||
const editingNameLength = computed(() =>
|
||||
Array.from(String(editingName.value || "")).length
|
||||
);
|
||||
|
||||
const isEditingNameTooLong = computed(
|
||||
() => editingNameLength.value > DEVICE_NAME_MAX_LENGTH
|
||||
);
|
||||
|
||||
const toggleDeviceId = () => {
|
||||
if (device.value.deviceId) showDeviceId.value = !showDeviceId.value;
|
||||
};
|
||||
@@ -162,8 +190,15 @@ const confirmName = async () => {
|
||||
uni.showToast({ title: "请输入设备名", icon: "none" });
|
||||
return;
|
||||
}
|
||||
if (name.length > 10 || !/^[\u4e00-\u9fa5A-Za-z0-9_-]+$/.test(name)) {
|
||||
uni.showToast({ title: "设备名格式不正确", icon: "none" });
|
||||
if (Array.from(name).length > DEVICE_NAME_MAX_LENGTH) {
|
||||
uni.showToast({ title: "设备名最多支持10个字符", icon: "none" });
|
||||
return;
|
||||
}
|
||||
if (!/^[\u4e00-\u9fa5A-Za-z0-9_-]+$/.test(name)) {
|
||||
uni.showToast({
|
||||
title: "仅支持中文、英文、数字、下划线和减号",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -206,7 +241,7 @@ const toDeviceIntroPage = () => {
|
||||
|
||||
const joinWifi = () => {
|
||||
if (!isDeviceOnline.value) {
|
||||
uni.showToast({ title: "请先开启智能弓箭", icon: "none" });
|
||||
uni.showToast({ title: "请先开启智能弓", icon: "none" });
|
||||
return;
|
||||
}
|
||||
uni.navigateTo({ url: "/pages/device/ota-wifi" });
|
||||
@@ -277,6 +312,52 @@ const closeLatestVersionDialog = () => {
|
||||
latestVersionDialogVisible.value = false;
|
||||
};
|
||||
|
||||
const closeFirmwareConfirm = () => {
|
||||
firmwareConfirmVisible.value = false;
|
||||
};
|
||||
|
||||
const runFirmwareUpdate = () => {
|
||||
const versionInfo = pendingOtaInfo.value;
|
||||
if (!versionInfo) return;
|
||||
void startOtaUpdate({
|
||||
versionNumber: versionInfo.versionNumber,
|
||||
resourceUrl: versionInfo.resourceUrl,
|
||||
onSuccess: () => {
|
||||
otaNeedUpdate.value = false;
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const confirmFirmwareUpdate = () => {
|
||||
firmwareConfirmVisible.value = false;
|
||||
if (!isDeviceOnline.value) {
|
||||
uni.showToast({ title: "请先开启智能弓", icon: "none" });
|
||||
return;
|
||||
}
|
||||
if (String(networkType.value || "").toLowerCase() === "wifi") {
|
||||
runFirmwareUpdate();
|
||||
return;
|
||||
}
|
||||
wifiRequiredVisible.value = true;
|
||||
};
|
||||
|
||||
const goWifiForFirmwareUpdate = () => {
|
||||
const versionInfo = pendingOtaInfo.value;
|
||||
if (!versionInfo) 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 handleOtaResultClose = () => {
|
||||
closeOtaResult();
|
||||
void refreshOtaUpdateState();
|
||||
};
|
||||
|
||||
const goFirmwareUpdate = async () => {
|
||||
if (firmwareActionPending.value) return;
|
||||
if (!isDeviceOnline.value) {
|
||||
@@ -293,11 +374,8 @@ const goFirmwareUpdate = async () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const query = [
|
||||
`versionNumber=${encodeURIComponent(versionInfo.versionNumber)}`,
|
||||
`resourceUrl=${encodeURIComponent(versionInfo.resourceUrl)}`,
|
||||
].join("&");
|
||||
uni.navigateTo({ url: `/pages/device/ota-wifi?${query}` });
|
||||
pendingOtaInfo.value = versionInfo;
|
||||
firmwareConfirmVisible.value = true;
|
||||
} catch (error) {
|
||||
uni.showToast({ title: "获取更新版本失败,请重试", icon: "none" });
|
||||
} finally {
|
||||
@@ -307,7 +385,7 @@ const goFirmwareUpdate = async () => {
|
||||
|
||||
const goCalibration = async () => {
|
||||
if (!isDeviceOnline.value) {
|
||||
uni.showToast({ title: "请先开启智能弓箭", icon: "none" });
|
||||
uni.showToast({ title: "请先开启智能弓", icon: "none" });
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -546,10 +624,16 @@ onShow(async () => {
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<ScreenHint mode="square" :show="showTip" :onClose="closeTip">
|
||||
<ModalDialog
|
||||
:show="showTip"
|
||||
:showCancel="false"
|
||||
:showConfirm="false"
|
||||
:showClose="true"
|
||||
:onClose="closeTip"
|
||||
>
|
||||
<view class="scan-tips">
|
||||
<text class="scan-tips-title">扫码绑定射灵弓箭</text>
|
||||
<text class="scan-tips-subtitle">设备底部二维码样例</text>
|
||||
<text class="scan-tips-subtitle">配套令牌样例</text>
|
||||
<image
|
||||
class="scan-tips-qr"
|
||||
src="../../static/device-assets/my-device-unbound-qr-sample.png"
|
||||
@@ -561,7 +645,7 @@ onShow(async () => {
|
||||
<button hover-class="none" @click="copyEmail">shelingxingqiu@163.com</button>
|
||||
</view>
|
||||
</view>
|
||||
</ScreenHint>
|
||||
</ModalDialog>
|
||||
|
||||
<ScreenHint :show="confirmBindTip" :onClose="closeConfirmBindTip">
|
||||
<view class="confirm-bind">
|
||||
@@ -598,6 +682,47 @@ onShow(async () => {
|
||||
:onConfirm="closeLatestVersionDialog"
|
||||
></ModalDialog>
|
||||
|
||||
<ModalDialog
|
||||
:show="firmwareConfirmVisible"
|
||||
title="固件更新"
|
||||
content="是否现在进行固件更新?"
|
||||
cancelText="取消"
|
||||
confirmText="确定"
|
||||
:onCancel="closeFirmwareConfirm"
|
||||
:onConfirm="confirmFirmwareUpdate"
|
||||
></ModalDialog>
|
||||
|
||||
<ModalDialog
|
||||
:show="wifiRequiredVisible"
|
||||
title="固件更新"
|
||||
content="请在WiFi网络下更新"
|
||||
confirmText="连接WiFi"
|
||||
:showCancel="false"
|
||||
:onConfirm="goWifiForFirmwareUpdate"
|
||||
></ModalDialog>
|
||||
|
||||
<OtaModal
|
||||
:visible="otaUpdating"
|
||||
state="update_progress"
|
||||
:progress="otaProgress"
|
||||
:phase="otaPhase"
|
||||
/>
|
||||
|
||||
<OtaModal
|
||||
:visible="otaResultVisible && otaResultStatus === 'success'"
|
||||
state="update_success"
|
||||
@done="handleOtaResultClose"
|
||||
/>
|
||||
|
||||
<ModalDialog
|
||||
:show="otaResultVisible && otaResultStatus === 'failed'"
|
||||
:title="otaResultTitle"
|
||||
:content="otaResultContent"
|
||||
confirmText="关闭"
|
||||
:showCancel="false"
|
||||
:onConfirm="handleOtaResultClose"
|
||||
></ModalDialog>
|
||||
|
||||
<view v-if="nameEditorVisible" class="name-mask" @click="closeNameEditor">
|
||||
<view class="name-panel" @click.stop>
|
||||
<image
|
||||
@@ -613,9 +738,9 @@ onShow(async () => {
|
||||
focus
|
||||
:cursor-spacing="24"
|
||||
:disabled="renaming"
|
||||
maxlength="10"
|
||||
:maxlength="-1"
|
||||
confirm-type="done"
|
||||
placeholder="请输入设备名(最长10个汉字)"
|
||||
placeholder="请输入设备名"
|
||||
placeholder-class="name-placeholder"
|
||||
@confirm="confirmName"
|
||||
/>
|
||||
@@ -631,7 +756,13 @@ onShow(async () => {
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<text class="name-helper">仅支持中文、英文、数字、下划线、减号</text>
|
||||
<view class="name-meta">
|
||||
<text class="name-helper">仅支持中文、英文、数字、下划线、减号</text>
|
||||
<text
|
||||
class="name-count"
|
||||
:class="{ 'name-count--exceeded': isEditingNameTooLong }"
|
||||
>{{ editingNameLength }}/{{ DEVICE_NAME_MAX_LENGTH }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -661,7 +792,7 @@ onShow(async () => {
|
||||
|
||||
.device-nav .device-status {
|
||||
position: absolute;
|
||||
top: calc(100% + 28rpx);
|
||||
top: calc(100% + 0);
|
||||
left: 50%;
|
||||
white-space: nowrap;
|
||||
transform: translateX(-50%);
|
||||
@@ -851,7 +982,7 @@ onShow(async () => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
font-size: 24rpx;
|
||||
font-size: 18rpx;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
|
||||
@@ -1120,12 +1251,13 @@ onShow(async () => {
|
||||
|
||||
.scan-tips {
|
||||
display: flex;
|
||||
width: 90%;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
margin-top: 20%;
|
||||
align-items: flex-start;
|
||||
color: #ffffff;
|
||||
font-size: 24rpx;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.scan-tips-title {
|
||||
@@ -1276,12 +1408,34 @@ onShow(async () => {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.name-helper {
|
||||
display: block;
|
||||
.name-meta {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
max-width: 620rpx;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
margin-top: 22rpx;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.name-helper,
|
||||
.name-count {
|
||||
color: rgba(255, 255, 255, 0.62);
|
||||
font-size: 24rpx;
|
||||
line-height: 34rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.name-helper {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.name-count {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.name-count--exceeded {
|
||||
color: #fed847;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user