Files
youlai-app/src/subPages/mine/settings/network/index.vue
T
Ray.Hao cb1a1e349f refactor: 组件就近迁移、操作菜单组件化并统一页面命名
- 组件文件统一 PascalCase 并就近迁入所属目录
- 操作菜单抽为 ActionSheet 组件,危险操作确认拆为 useConfirmAction
- 导航栏测量拆为 useNavbarMetrics 并收缩对外接口
- 页面方法按动词约定重命名,show 前缀与 handle 误用一并修正
- 通知与菜单接口类型改用字面量联合并修正取值注释
- 多行空壳注释收回单行
2026-10-16 16:50:56 +08:00

174 lines
4.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="network">
<view class="pt-8rpx">
<text class="network__tip-text">
温馨提示:点击下方「开始测试」按钮,即可检测当前网络到接口服务的连接质量。
</text>
</view>
<view class="mt-16rpx">
<wd-button block variant="plain" :loading="isTesting" @click="startTest">开始测试</wd-button>
</view>
<view v-if="isTesting" class="network__loading">
<wd-loading color="var(--wot-color-theme)" />
<text class="network__loading-text">正在测试中...</text>
</view>
<view v-if="result" class="network__result">
<view class="result-card">
<view class="result-card__header">测试结果</view>
<view class="result-card__row">
<text class="result-card__label">接口服务</text>
<text
class="result-card__value"
:class="result.reachable ? 'color-success' : 'color-danger'"
>
{{ result.reachable ? "可访问" : "不可访问" }}
</text>
</view>
<view class="result-card__row">
<text class="result-card__label">响应耗时</text>
<text class="text-36rpx font-600" :class="statusColor">
{{ result.costMs === null ? "--" : `${result.costMs}ms` }}
</text>
</view>
<view class="result-card__row">
<text class="result-card__label">网络状态</text>
<text class="font-500" :class="statusColor">{{ statusText }}</text>
</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
definePage({
name: "network",
style: { navigationBarTitleText: "网络检测" },
});
// 一次探测的结果:可达性用布尔值,耗时单独记录,不可达时不参与质量分档
interface ProbeResult {
reachable: boolean;
costMs: number | null;
}
const result = ref<ProbeResult | null>(null);
const isTesting = ref(false);
// 耗时分档:100ms 以内优秀,300ms 以内良好,500ms 以内一般,其余较差
const statusText = computed(() => {
if (!result.value) return "";
if (!result.value.reachable) return "不可访问";
const cost = result.value.costMs ?? 0;
if (cost < 100) return "优秀";
if (cost < 300) return "良好";
if (cost < 500) return "一般";
return "较差";
});
const statusColor = computed(() => {
if (!result.value) return "";
if (!result.value.reachable) return "color-danger";
const cost = result.value.costMs ?? 0;
if (cost < 100) return "color-success";
if (cost < 300) return "color-primary";
if (cost < 500) return "color-warning";
return "color-danger";
});
// 探测目标:与请求层同源,微信端用完整地址,其余端走代理前缀
function getProbeUrl(): string {
let baseUrl = import.meta.env.VITE_APP_BASE_API;
// #ifdef MP-WEIXIN
baseUrl = import.meta.env.VITE_APP_API_URL;
// #endif
return `${baseUrl}/`;
}
// 探测接口服务地址:拿到响应即视为可达,状态码不参与判断
async function startTest() {
if (isTesting.value) return;
isTesting.value = true;
result.value = null;
const startedAt = Date.now();
try {
await new Promise<void>((resolve, reject) => {
uni.request({
url: getProbeUrl(),
method: "GET",
timeout: 10000,
// 接口服务地址本身没有业务数据,只要拿到响应即说明链路可达,状态码不参与判断
success: () => resolve(),
fail: (error) => reject(error),
});
});
result.value = { reachable: true, costMs: Date.now() - startedAt };
} catch {
result.value = { reachable: false, costMs: null };
} finally {
isTesting.value = false;
}
}
</script>
<style lang="scss" scoped>
.result-card {
overflow: hidden;
background: var(--color-bg-card);
border: 1rpx solid var(--color-border);
border-radius: 16rpx;
&__header {
padding: 24rpx;
font-size: 32rpx;
font-weight: 600;
border-bottom: 1rpx solid var(--color-border);
}
&__row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx;
& + & {
border-top: 1rpx solid var(--color-border-light);
}
}
&__label {
color: var(--color-text-secondary);
}
&__value {
font-weight: 500;
}
}
.network__tip-text {
font-size: 24rpx;
color: var(--color-text-placeholder);
}
.network__loading {
display: flex;
flex-direction: column;
align-items: center;
padding: 40rpx 0;
}
.network__loading-text {
margin-top: 16rpx;
font-size: 24rpx;
color: var(--color-text-secondary);
}
.network__result {
margin-top: 24rpx;
}
</style>