update:优化wifi

This commit is contained in:
2026-09-23 18:33:12 +08:00
parent 169e2e4a51
commit 78fd64c697
3 changed files with 386 additions and 280 deletions
+7
View File
@@ -592,6 +592,13 @@ export const connectDeviceWifiAPI = async (ssid, password) => {
); );
}; };
// 查询设备当前联网类型及已连接的 WiFi 名称。
export const getDeviceWifiStatusAPI = async () => {
return request("GET", "/user/device/wifiStatus", {}, BASE_URL, [0], {
showErrorToast: false,
});
};
// 获取硬件盒子版本信息,用于判断当前设备是否需要 OTA 升级。 // 获取硬件盒子版本信息,用于判断当前设备是否需要 OTA 升级。
export const getHardwareBoxVersionAPI = async () => { export const getHardwareBoxVersionAPI = async () => {
return request("GET", "/user/hardwareBox/version"); return request("GET", "/user/hardwareBox/version");
+379 -280
View File
@@ -1,12 +1,15 @@
<script setup> <script setup>
import { ref, computed, onMounted, onUnmounted } from "vue"; import { ref, computed, watch, onMounted, onUnmounted } from "vue";
import { onLoad, onShow } from "@dcloudio/uni-app"; import { onLoad, onShow } from "@dcloudio/uni-app";
import { storeToRefs } from "pinia";
import Container from "@/components/Container.vue"; import Container from "@/components/Container.vue";
import ScreenHint from "@/components/ScreenHint.vue";
import ModalDialog from "@/components/ModalDialog.vue"; import ModalDialog from "@/components/ModalDialog.vue";
import OtaModal from "@/components/OtaModal.vue"; import OtaModal from "@/components/OtaModal.vue";
import useStore from "@/store";
import { capsuleHeight } from "@/util";
import { import {
connectDeviceWifiAPI, connectDeviceWifiAPI,
getDeviceWifiStatusAPI,
getHardwareBoxVersionAPI, getHardwareBoxVersionAPI,
} from "@/apis"; } from "@/apis";
import { useOtaUpdate } from "@/composables/useOtaUpdate"; import { useOtaUpdate } from "@/composables/useOtaUpdate";
@@ -16,11 +19,17 @@ const STATES = {
LIST: "LIST", LIST: "LIST",
CONNECTING: "CONNECTING", CONNECTING: "CONNECTING",
CONNECTED: "CONNECTED", CONNECTED: "CONNECTED",
LOCATION_REQUIRED: "LOCATION_REQUIRED",
}; };
const isIOS = uni.getDeviceInfo().osName === "ios"; const isIOS = uni.getDeviceInfo().osName === "ios";
const { deviceStatus } = storeToRefs(useStore());
const currentState = ref(STATES.SCANNING); const currentState = ref(STATES.SCANNING);
const connectedWifi = ref(null); const connectedWifi = ref(null);
const connectedWifiName = ref("");
const isDeviceOnWifi = computed(
() => deviceStatus.value.online === true && deviceStatus.value.netType === "wifi"
);
const wifiList = ref([]); const wifiList = ref([]);
const showWifiBanner = ref(false); const showWifiBanner = ref(false);
@@ -46,9 +55,17 @@ const firmwareMessageVisible = ref(false);
const firmwareMessage = ref(""); const firmwareMessage = ref("");
let countdownTimer = null; let countdownTimer = null;
let wifiConnectRequestId = 0; let wifiConnectRequestId = 0;
let wifiStatusRequestId = 0;
const WIFI_CONNECT_FAILED_TEXT = "连接失败,请检查WiFi密码或WiFi状态"; const WIFI_CONNECT_FAILED_TEXT = "连接失败,请检查WiFi密码或WiFi状态";
// 控制授权拒绝弹窗显示/隐藏 // 与 Container 的可滚动区域保持一致,底部说明在长短屏上都能贴近安全区。
const wifiAuthDeniedVisible = ref(false); const windowInfo = uni.getWindowInfo();
const contentMinHeight = Math.max(
0,
Math.round(
(windowInfo.windowHeight - capsuleHeight - 50) *
(750 / windowInfo.windowWidth)
)
);
const { const {
updating: otaUpdating, updating: otaUpdating,
@@ -73,20 +90,29 @@ const isWifiPermissionDenied = (err) => {
return /auth den|authorize|permission denied|user denied|scope\.userLocation/i.test(errMsg); return /auth den|authorize|permission denied|user denied|scope\.userLocation/i.test(errMsg);
}; };
// 显示授权拒绝弹窗,通过 ScreenHint 组件呈现 // Android 定位不可用时展示蓝湖中的独立引导状态
const showWifiPermissionDeniedModal = () => { const showLocationPermission = () => {
wifiAuthDeniedVisible.value = true; currentState.value = STATES.LOCATION_REQUIRED;
isRefreshing.value = false;
}; };
// 用户点击「重新授权」时,打开小程序权限设置页,引导用户开启位置权限后重新扫描 // 已拒绝授权时进入小程序设置;首次授权则重新扫描以触发系统权限流程
const handleReauthorize = () => { const handleReauthorize = () => {
wifiAuthDeniedVisible.value = false; if (uni.getSystemSetting().locationEnabled === false) {
uni.openSetting({ uni.showToast({ title: "请先开启手机定位服务", icon: "none" });
return;
}
uni.getSetting({
success(res) { success(res) {
// 若用户在设置页开启了位置权限,则重新启动 WiFi 扫描 if (res.authSetting["scope.userLocation"] !== false) {
if (res.authSetting["scope.userLocation"]) {
startScanning(); startScanning();
return;
} }
uni.openSetting({
success(setting) {
if (setting.authSetting["scope.userLocation"]) startScanning();
},
});
}, },
}); });
}; };
@@ -96,7 +122,7 @@ const applyIOSConnectedWifi = (wifi) => {
const ssid = wifi?.SSID; const ssid = wifi?.SSID;
if (!ssid) { if (!ssid) {
wifiList.value = []; wifiList.value = [];
currentState.value = STATES.LIST; currentState.value = connectedWifi.value ? STATES.CONNECTED : STATES.LIST;
isRefreshing.value = false; isRefreshing.value = false;
return; return;
} }
@@ -109,7 +135,7 @@ const applyIOSConnectedWifi = (wifi) => {
fromCurrentWifi: true, fromCurrentWifi: true,
}, },
]; ];
currentState.value = STATES.LIST; currentState.value = connectedWifi.value ? STATES.CONNECTED : STATES.LIST;
isRefreshing.value = false; isRefreshing.value = false;
}; };
@@ -127,7 +153,7 @@ const syncIOSConnectedWifi = () => {
err, err,
}); });
wifiList.value = []; wifiList.value = [];
currentState.value = STATES.LIST; currentState.value = connectedWifi.value ? STATES.CONNECTED : STATES.LIST;
isRefreshing.value = false; isRefreshing.value = false;
}, },
}); });
@@ -147,7 +173,7 @@ const startIOSScanning = () => {
err, err,
}); });
if (err.errCode === 12005) showWifiBanner.value = true; if (err.errCode === 12005) showWifiBanner.value = true;
currentState.value = STATES.LIST; currentState.value = connectedWifi.value ? STATES.CONNECTED : STATES.LIST;
isRefreshing.value = false; isRefreshing.value = false;
}, },
}); });
@@ -168,6 +194,11 @@ const startScanning = () => {
return; return;
} }
if (uni.getSystemSetting().locationEnabled === false) {
showLocationPermission();
return;
}
wx.startWifi({ wx.startWifi({
success(res) { success(res) {
console.log("[OTA WiFi] wx.startWifi success:", res); console.log("[OTA WiFi] wx.startWifi success:", res);
@@ -181,7 +212,11 @@ const startScanning = () => {
errMsg: err?.errMsg, errMsg: err?.errMsg,
err, err,
}); });
if (isWifiPermissionDenied(err)) showWifiPermissionDeniedModal(); if (isWifiPermissionDenied(err)) {
showLocationPermission();
} else {
currentState.value = connectedWifi.value ? STATES.CONNECTED : STATES.LIST;
}
if (err.errCode === 12005) showWifiBanner.value = true; if (err.errCode === 12005) showWifiBanner.value = true;
isRefreshing.value = false; isRefreshing.value = false;
}, },
@@ -193,13 +228,18 @@ const startScanning = () => {
errMsg: err?.errMsg, errMsg: err?.errMsg,
err, err,
}); });
if (isWifiPermissionDenied(err)) showWifiPermissionDeniedModal(); if (isWifiPermissionDenied(err)) {
showLocationPermission();
} else {
currentState.value = connectedWifi.value ? STATES.CONNECTED : STATES.LIST;
}
if (err.errCode === 12005) showWifiBanner.value = true; if (err.errCode === 12005) showWifiBanner.value = true;
isRefreshing.value = false; isRefreshing.value = false;
}, },
}); });
wx.onGetWifiList((res) => { wx.onGetWifiList((res) => {
if (currentState.value === STATES.LOCATION_REQUIRED) return;
const realWifiList = res.wifiList || []; const realWifiList = res.wifiList || [];
if (realWifiList.length) { if (realWifiList.length) {
console.log("[OTA WiFi] wx.onGetWifiList received wifiList:", realWifiList); console.log("[OTA WiFi] wx.onGetWifiList received wifiList:", realWifiList);
@@ -207,7 +247,7 @@ const startScanning = () => {
console.warn("[OTA WiFi] wx.onGetWifiList received empty wifiList:", res); console.warn("[OTA WiFi] wx.onGetWifiList received empty wifiList:", res);
} }
wifiList.value = realWifiList; wifiList.value = realWifiList;
currentState.value = STATES.LIST; currentState.value = connectedWifi.value ? STATES.CONNECTED : STATES.LIST;
isRefreshing.value = false; isRefreshing.value = false;
}); });
}; };
@@ -256,12 +296,31 @@ const joinDisabled = computed(() => {
return false; return false;
}); });
// 按当前页面状态限制 WiFi 列表高度,避免列表撑开整页 // 列表按实际条目收起;空间不足时由页面布局限制高度并在卡片内滚动
const wifiListScrollHeight = computed(() => { const wifiListScrollHeight = computed(() => {
if (currentState.value === STATES.SCANNING) return "auto";
const itemCount = wifiList.value.length + 1; const itemCount = wifiList.value.length + 1;
const maxHeight = currentState.value === STATES.CONNECTED ? 276 : 420; return `${itemCount * 108}rpx`;
return `${Math.min(itemCount * 92, maxHeight)}rpx`; });
// 展示条件只取 WebSocket 设备状态;接口仅提供名称,过期请求不得覆盖新状态。
const refreshConnectedWifiName = async () => {
const requestId = ++wifiStatusRequestId;
if (!isDeviceOnWifi.value) {
connectedWifiName.value = "";
return;
}
connectedWifiName.value = "";
try {
const status = await getDeviceWifiStatusAPI();
if (requestId !== wifiStatusRequestId || !isDeviceOnWifi.value) return;
connectedWifiName.value = String(status?.ssid ?? "").trim();
} catch (error) {
if (requestId === wifiStatusRequestId) connectedWifiName.value = "";
}
};
watch(isDeviceOnWifi, () => {
void refreshConnectedWifiName();
}); });
// 取消当前 WiFi 连接请求的页面等待状态,并忽略可能迟到的响应。 // 取消当前 WiFi 连接请求的页面等待状态,并忽略可能迟到的响应。
@@ -309,6 +368,7 @@ const submitDeviceWifiConfig = async ({ ssid, password }) => {
}; };
connectError.value = ""; connectError.value = "";
currentState.value = STATES.CONNECTED; currentState.value = STATES.CONNECTED;
void refreshConnectedWifiName();
if (fromFirmwareUpdate.value) { if (fromFirmwareUpdate.value) {
openFirmwareCountdown(); openFirmwareCountdown();
} }
@@ -388,7 +448,9 @@ const openFirmwareCountdown = () => {
// 监听系统输入法高度,用于让底部弹窗避开键盘遮挡。 // 监听系统输入法高度,用于让底部弹窗避开键盘遮挡。
const handleKeyboardHeightChange = (res) => { const handleKeyboardHeightChange = (res) => {
keyboardHeight.value = res?.height || 0; keyboardHeight.value = Math.round(
(res?.height || 0) * (750 / windowInfo.windowWidth)
);
}; };
// 切换密码显示状态前先收起键盘,避免安全键盘和普通输入法切换时复用旧高度产生黑条。 // 切换密码显示状态前先收起键盘,避免安全键盘和普通输入法切换时复用旧高度产生黑条。
@@ -420,12 +482,24 @@ onMounted(() => {
// iOS 从系统 WiFi 设置返回小程序后,同步当前手机连接的 WiFi。 // iOS 从系统 WiFi 设置返回小程序后,同步当前手机连接的 WiFi。
onShow(() => { onShow(() => {
void refreshConnectedWifiName();
if (isIOS && currentState.value === STATES.LIST) { if (isIOS && currentState.value === STATES.LIST) {
syncIOSConnectedWifi(); syncIOSConnectedWifi();
} else if (
!isIOS &&
currentState.value === STATES.LOCATION_REQUIRED &&
uni.getSystemSetting().locationEnabled !== false
) {
uni.getSetting({
success(res) {
if (res.authSetting["scope.userLocation"] !== false) startScanning();
},
});
} }
}); });
onUnmounted(() => { onUnmounted(() => {
wifiStatusRequestId += 1;
if (typeof uni.offKeyboardHeightChange === "function") { if (typeof uni.offKeyboardHeightChange === "function") {
uni.offKeyboardHeightChange(handleKeyboardHeightChange); uni.offKeyboardHeightChange(handleKeyboardHeightChange);
} }
@@ -436,103 +510,143 @@ onUnmounted(() => {
</script> </script>
<template> <template>
<Container title="连接无线网络"> <Container :scroll="false">
<!-- WiFi 不可用 Banner --> <!-- WiFi 不可用 Banner -->
<view v-if="showWifiBanner" class="wifi-banner"> <view v-if="showWifiBanner" class="wifi-banner">
<text class="wifi-banner-text">请先开启 WiFi 后刷新重试</text> <text class="wifi-banner-text">请先开启 WiFi 后刷新重试</text>
</view> </view>
<!-- SCANNING / LIST / CONNECTED --> <!-- 扫描候选网络与设备已连接网络共用页面主体 -->
<view <view
v-if="currentState === 'SCANNING' || currentState === 'LIST' || currentState === 'CONNECTED'" v-if="currentState === 'SCANNING' || currentState === 'LIST' || currentState === 'CONNECTED'"
class="wifi-page" class="wifi-page"
:style="{ height: contentMinHeight + 'rpx' }"
> >
<!-- Hero: wifi1.png 单图已内含吉祥物 -->
<view class="hero-area"> <view class="hero-area">
<image src="https://static.shelingxingqiu.com/shootmini/static/ota/wifi1.png" mode="aspectFit" style="width: 194rpx; height: 164rpx;" /> <image
class="hero-image"
src="https://static.shelingxingqiu.com/shootmini/static/ota/wifi1.png"
mode="aspectFit"
/>
</view> </view>
<text class="page-title">智能弓箭连接无线网络</text>
<text class="page-subtitle">提醒本操作将为智能弓箭连接WIFI网络不会影响手机自身连接的WIFI网络</text>
<text class="page-title" :class="{ 'connected-page-title': currentState === 'CONNECTED' }"> <view class="network-sections">
{{ currentState === 'CONNECTED' ? '连接成功' : '连接无线网络' }} <!-- 仅设备 WebSocket 状态为 WiFi 时显示此卡片不触发密码输入 -->
</text> <view v-if="isDeviceOnWifi && connectedWifiName" class="network-section connected-section">
<text v-if="currentState !== 'CONNECTED'" class="page-subtitle">网络名称仅支持英文字符及数字</text> <text class="section-label">已连接</text>
<view class="connected-wifi-card">
<view v-if="isIOS && currentState !== 'CONNECTED'" class="ios-guide"> <text class="wifi-ssid">{{ connectedWifiName }}</text>
<text class="ios-guide-text">请先在系统 WiFi 设置中连接目标网络返回后选择当前 WiFi 并填写密码</text>
</view>
<!-- 已连接网络卡片 -->
<view v-if="currentState === 'CONNECTED'" class="section-label-row connected-section-label-row">
<text class="section-label">连接网络</text>
</view>
<view v-if="currentState === 'CONNECTED'" class="wifi-list-card connected-wifi-card">
<view class="wifi-item connected-wifi-item">
<image class="check-icon" src="https://static.shelingxingqiu.com/shootmini/static/sicon/check.png" mode="aspectFit" />
<text class="wifi-ssid connected-wifi-ssid">{{ connectedWifi?.SSID }}</text>
<view class="wifi-icons connected-wifi-icons">
<image <image
v-if="connectedWifi?.secure" class="check-icon"
class="security-icon" src="https://static.shelingxingqiu.com/shootmini/static/sicon/check.png"
src="https://static.shelingxingqiu.com/shootmini/static/sicon/pwd.png"
mode="aspectFit" mode="aspectFit"
/> />
<image class="signal-icon" src="https://static.shelingxingqiu.com/shootmini/static/sicon/wifi.png" mode="aspectFit" />
</view> </view>
</view> </view>
<view class="network-section">
<view class="section-label-row">
<text class="section-label">选择网络</text>
<image
class="refresh-icon"
src="https://static.shelingxingqiu.com/shootmini/static/sicon/refresh.png"
mode="aspectFit"
:style="{ opacity: isRefreshing ? 0.3 : 0.6 }"
@click="startScanning"
/>
</view>
<block v-if="isIOS">
<view
v-if="wifiList.length"
class="ios-network-card current-network-card"
@click="selectWifi(wifiList[0])"
>
<view class="network-copy">
<text class="wifi-ssid">{{ wifiList[0].SSID }}</text>
<text class="network-desc">手机当前连接的网络</text>
</view>
<image
class="signal-icon"
src="https://static.shelingxingqiu.com/shootmini/static/sicon/wifi.png"
mode="aspectFit"
/>
</view>
<view class="ios-network-card manual-network-card" @click="selectOther">
<view class="network-copy">
<text class="wifi-ssid">手动连接其他网络</text>
<text class="network-desc">由于权限限制无法获取附近网络列表如需连接其他网络请手动输入网络名称与密码进行连接</text>
</view>
<image
class="signal-icon"
src="https://static.shelingxingqiu.com/shootmini/static/sicon/wifi.png"
mode="aspectFit"
/>
</view>
</block>
<scroll-view
v-else
scroll-y
class="android-list-card"
:style="{ maxHeight: wifiListScrollHeight }"
>
<view
v-for="wifi in wifiList"
:key="wifi.SSID"
class="android-network-item"
@click="selectWifi(wifi)"
>
<text class="wifi-ssid">{{ wifi.SSID }}</text>
<view class="wifi-icons">
<image
v-if="wifi.secure"
class="security-icon"
src="https://static.shelingxingqiu.com/shootmini/static/sicon/pwd.png"
mode="aspectFit"
/>
<image
class="signal-icon"
src="https://static.shelingxingqiu.com/shootmini/static/sicon/wifi.png"
mode="aspectFit"
/>
</view>
</view>
<view class="android-network-item manual-network-item" @click="selectOther">
<text class="wifi-ssid">手动连接其他网络</text>
</view>
</scroll-view>
</view>
</view> </view>
<!-- 网络列表标题 --> <text class="wifi-footer">智能弓箭目前仅支持保存一条网络信息若连接新的网络将删除上一条网络信息</text>
<view class="section-label-row"> </view>
<text class="section-label">网络</text>
<!-- Android 定位权限不足时的整页引导状态 -->
<view
v-if="currentState === 'LOCATION_REQUIRED'"
class="location-page"
:style="{ minHeight: contentMinHeight + 'rpx' }"
>
<view class="location-image-wrap">
<image <image
src="https://static.shelingxingqiu.com/shootmini/static/sicon/refresh.png" class="location-image"
src="https://static.shelingxingqiu.com/shootmini/static/device-assets/wifi-location.png"
mode="aspectFit" mode="aspectFit"
:style="{ width: '34rpx', height: '34rpx', marginLeft: '8rpx', opacity: isRefreshing ? 0.3 : 0.7 }"
@click="startScanning"
/> />
<view class="location-shadow"></view>
</view>
<text class="location-desc">请授权允许获取定位信息并开启定位功能以查找附近可用无线网络</text>
<view class="location-button" @click="handleReauthorize">
<text>授权获取定位信息</text>
</view> </view>
<!-- 网络列表卡片 -->
<scroll-view
scroll-y
class="wifi-list-card"
:class="{ 'wifi-list-scroll': currentState !== 'SCANNING' }"
:style="{ height: wifiListScrollHeight }"
>
<block v-if="currentState === 'SCANNING'">
<view class="wifi-item" @click="selectOther">
<text class="wifi-ssid other-text">其他...</text>
</view>
</block>
<block v-else>
<view
v-for="(wifi, idx) in wifiList"
:key="wifi.SSID"
class="wifi-item"
@click="selectWifi(wifi)"
>
<text class="wifi-ssid">{{ wifi.SSID }}</text>
<view class="wifi-icons">
<image
v-if="wifi.secure"
class="security-icon"
src="https://static.shelingxingqiu.com/shootmini/static/sicon/pwd.png"
mode="aspectFit"
/>
<image class="signal-icon" src="https://static.shelingxingqiu.com/shootmini/static/sicon/wifi.png" mode="aspectFit" />
</view>
</view>
<view class="wifi-item" @click="selectOther">
<text class="wifi-ssid other-text">其他...</text>
</view>
</block>
</scroll-view>
</view> </view>
<!-- CONNECTING 底部弹窗 --> <!-- CONNECTING 底部弹窗 -->
<view v-if="currentState === 'CONNECTING'" class="sheet-mask"> <view v-if="currentState === 'CONNECTING'" class="sheet-mask">
<view class="sheet" :style="{ marginBottom: keyboardHeight + 'px' }" @click.stop=""> <view class="sheet" :style="{ marginBottom: keyboardHeight + 'rpx' }" @click.stop="">
<image src="https://static.shelingxingqiu.com/shootmini/static/ota/ota-bg.png" mode="aspectFill" class="sheet-bg" /> <image src="https://static.shelingxingqiu.com/shootmini/static/ota/ota-bg.png" mode="aspectFill" class="sheet-bg" />
<view class="sheet-inner"> <view class="sheet-inner">
@@ -646,21 +760,6 @@ onUnmounted(() => {
</view> </view>
</view> </view>
<!-- 授权拒绝弹窗 -->
<ScreenHint :show="wifiAuthDeniedVisible" :onClose="() => (wifiAuthDeniedVisible = false)">
<view class="wifi-auth-denied">
<text class="wifi-auth-denied-text">拒绝授权获取wifi列表失败请重新授权或手动输入</text>
<view class="wifi-auth-denied-btns">
<view class="wifi-auth-denied-btn cancel-btn" @click="wifiAuthDeniedVisible = false">
<text>取消授权</text>
</view>
<view class="wifi-auth-denied-btn confirm-btn" @click="handleReauthorize">
<text>重新授权</text>
</view>
</view>
</view>
</ScreenHint>
<ModalDialog <ModalDialog
:show="countdownVisible" :show="countdownVisible"
title="WiFi连接成功" title="WiFi连接成功"
@@ -704,45 +803,6 @@ onUnmounted(() => {
</template> </template>
<style scoped> <style scoped>
.wifi-auth-denied {
display: flex;
flex-direction: column;
align-items: center;
padding: 32rpx 40rpx 24rpx;
gap: 32rpx;
}
.wifi-auth-denied-text {
color: #fff;
font-size: 28rpx;
text-align: center;
line-height: 1.6;
}
.wifi-auth-denied-btns {
display: flex;
flex-direction: row;
gap: 24rpx;
width: 100%;
justify-content: center;
}
.wifi-auth-denied-btn {
flex: 1;
height: 72rpx;
border-radius: 36rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
}
.wifi-auth-denied-btn.cancel-btn {
background: rgba(255, 255, 255, 0.15);
color: #fff;
}
.wifi-auth-denied-btn.confirm-btn {
background: rgba(254, 216, 71, 1);
color: #1a1a2e;
font-weight: 600;
}
.wifi-banner { .wifi-banner {
background-color: rgba(255, 200, 0, 0.12); background-color: rgba(255, 200, 0, 0.12);
border: 1rpx solid rgba(254, 216, 71, 0.5); border: 1rpx solid rgba(254, 216, 71, 0.5);
@@ -756,200 +816,239 @@ onUnmounted(() => {
} }
.wifi-page { .wifi-page {
padding: 0 67rpx 40rpx; box-sizing: border-box;
padding: 0 40rpx 54rpx;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden;
} }
.hero-area { .hero-area {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
padding: 40rpx 0 24rpx; margin-top: 12rpx;
}
.hero-image {
width: 164rpx;
height: 152rpx;
} }
.page-title { .page-title {
color: rgba(91, 196, 255, 1); display: block;
color: #5fadff;
font-size: 36rpx; font-size: 36rpx;
line-height: 50rpx;
font-weight: 600; font-weight: 600;
text-align: center; text-align: center;
margin-bottom: 8rpx; margin-top: 22rpx;
}
.connected-page-title {
color: #4DD9C8;
} }
.page-subtitle { .page-subtitle {
color: rgba(255, 255, 255, 0.5); display: block;
align-self: center;
width: 552rpx;
max-width: 100%;
color: #fff;
font-size: 24rpx; font-size: 24rpx;
line-height: 34rpx;
text-align: center; text-align: center;
margin-bottom: 32rpx; margin-top: 4rpx;
} }
.fail-title { .network-sections {
color: rgba(255, 100, 100, 1); margin-top: 60rpx;
display: flex;
flex: 1;
flex-direction: column;
min-height: 0;
} }
.network-section:last-child {
.ios-guide { display: flex;
background-color: rgba(95, 173, 255, 0.12); flex: 1;
border-radius: 8rpx; flex-direction: column;
padding: 16rpx 24rpx; min-height: 0;
margin-bottom: 20rpx;
} }
.ios-guide-text { .connected-section {
color: rgba(95, 173, 255, 1); margin-bottom: 60rpx;
flex-shrink: 0;
}
.section-label {
display: block;
color: rgba(255, 255, 255, 0.6);
font-size: 26rpx; font-size: 26rpx;
line-height: 36rpx;
} }
.section-label-row { .section-label-row {
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 24rpx; justify-content: space-between;
padding: 0 22rpx; height: 36rpx;
} margin: 0 40rpx 20rpx;
.connected-section-label-row {
margin-top: 32rpx;
}
.section-label {
color: rgba(255, 255, 255, 0.56);
font-size: 28rpx;
}
.wifi-list-card {
background-color: rgba(30, 35, 50, 0.96);
border-radius: 24rpx;
overflow: hidden;
margin-bottom: 20rpx;
}
.wifi-list-scroll {
flex-shrink: 0; flex-shrink: 0;
} }
.connected-wifi-card { .connected-section > .section-label {
background-color: rgba(35, 40, 56, 0.96); margin: 0 40rpx 20rpx;
margin-bottom: 44rpx;
} }
.wifi-item { .refresh-icon {
position: relative; width: 30rpx;
height: 30rpx;
}
.connected-wifi-card,
.ios-network-card,
.android-list-card {
box-sizing: border-box;
background-color: rgba(255, 255, 255, 0.08);
border-radius: 24rpx;
overflow: hidden;
}
.connected-wifi-card {
height: 104rpx;
padding: 0 40rpx;
display: flex; display: flex;
align-items: center; align-items: center;
min-height: 92rpx; justify-content: space-between;
padding: 0 26rpx 0 66rpx;
}
.wifi-item:not(:last-child)::after {
content: "";
position: absolute;
left: 66rpx;
right: 26rpx;
bottom: 0;
height: 1rpx;
background-color: rgba(255, 255, 255, 0.08);
}
.connected-wifi-item {
min-height: 88rpx;
padding-left: 28rpx;
} }
.wifi-ssid { .wifi-ssid {
color: rgba(255, 255, 255, 1); display: block;
font-size: 28rpx; min-width: 0;
line-height: 36rpx; flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: #fff;
font-size: 32rpx;
line-height: 44rpx;
margin-bottom: 8rpx;
}
.ios-network-card {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 40rpx;
}
.current-network-card {
height: 124rpx;
}
.manual-network-card {
height: 156rpx;
margin-top: 20rpx;
}
.network-copy {
display: flex;
flex-direction: column;
justify-content: center;
min-width: 0;
flex: 1; flex: 1;
} }
.connected-wifi-ssid { .network-desc {
font-weight: 500; display: block;
color: rgba(255, 255, 255, 0.6);
font-size: 22rpx;
line-height: 32rpx;
} }
.other-text { .manual-network-card .network-desc {
color: rgba(255, 255, 255, 0.86); max-width: 484rpx;
}
.android-list-card {
padding: 0 40rpx;
flex: 1;
height: 0;
min-height: 0;
}
.android-network-item {
box-sizing: border-box;
height: 108rpx;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 2rpx solid rgba(255, 255, 255, 0.15);
}
.android-network-item:last-child {
border-bottom: none;
} }
.wifi-icons { .wifi-icons {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12rpx; gap: 16rpx;
flex-shrink: 0; flex-shrink: 0;
} }
.connected-wifi-icons {
gap: 14rpx;
}
.check-icon { .check-icon {
width: 28rpx; width: 40rpx;
height: 24rpx; height: 32rpx;
margin-right: 16rpx;
flex-shrink: 0; flex-shrink: 0;
} }
.security-icon { .security-icon {
width: 24rpx; width: 24rpx;
height: 30rpx; height: 28rpx;
flex-shrink: 0; flex-shrink: 0;
} }
.signal-icon { .signal-icon {
width: 36rpx; width: 40rpx;
height: 32rpx; height: 32rpx;
flex-shrink: 0; flex-shrink: 0;
} }
.wifi-footer {
.bottom-btn-area { display: block;
margin-top: 24rpx; flex-shrink: 0;
} align-self: center;
.connected-bottom-btn-area { width: 550rpx;
display: flex; max-width: 100%;
justify-content: center; margin-top: auto;
margin-top: 20rpx; padding-top: 60rpx;
} color: rgba(255, 255, 255, 0.6);
font-size: 22rpx;
.primary-btn { line-height: 32rpx;
background-color: rgba(254, 216, 71, 1);
border-radius: 50rpx;
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
}
.update-btn {
width: 412rpx;
}
.primary-btn-text {
color: rgba(0, 0, 0, 1);
font-size: 30rpx;
font-weight: 500;
}
.center-page {
display: flex;
flex-direction: column;
align-items: center;
padding: 80rpx 32rpx 40rpx;
}
.page-desc-white {
color: rgba(255, 255, 255, 1);
font-size: 28rpx;
line-height: 52rpx;
text-align: center; text-align: center;
} }
.done-btn { .location-page {
width: 80%; box-sizing: border-box;
} padding: 0 40rpx 54rpx;
.progress-wrap {
width: 80%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
gap: 16rpx;
margin-top: 40rpx;
} }
.progress-track { .location-image-wrap {
width: 100%; position: relative;
height: 10rpx; width: 200rpx;
background-color: rgba(255, 255, 255, 0.15); height: 266rpx;
border-radius: 5rpx; margin-top: 212rpx;
overflow: hidden;
} }
.progress-fill { .location-image {
height: 100%; position: relative;
background-color: rgba(91, 196, 255, 1); z-index: 1;
border-radius: 5rpx; width: 200rpx;
transition: width 0.4s ease; height: 266rpx;
} }
.progress-pct { .location-shadow {
color: rgba(91, 196, 255, 1); position: absolute;
left: 34rpx;
bottom: -22rpx;
width: 132rpx;
height: 50rpx;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.08);
}
.location-desc {
display: block;
width: 560rpx;
max-width: 100%;
margin-top: 48rpx;
color: #fff;
font-size: 28rpx; font-size: 28rpx;
line-height: 40rpx;
text-align: center;
}
.location-button {
box-sizing: border-box;
width: 364rpx;
height: 74rpx;
margin-top: 38rpx;
border: 2rpx solid #ffd800;
border-radius: 40rpx;
display: flex;
align-items: center;
justify-content: center;
color: #fed847;
font-size: 26rpx;
font-weight: 600; font-weight: 600;
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB