update:优化wifi
This commit is contained in:
@@ -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
@@ -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 |
Reference in New Issue
Block a user