可切換內網訪問
This commit is contained in:
1 parent
1ff69f3cb3
commit
fd67fa8f63
10 files changed
+493
-40
No files matched your search
@@ -6,7 +6,8 @@
|
||||
* 版本号取 common/constant 的 APP_INFO(与 manifest/package 对齐);H5 无 plus.runtime.version。
|
||||
*/
|
||||
import { useLocale } from "uview-pro";
|
||||
import { computed } from "vue";
|
||||
import { computed, ref } from "vue";
|
||||
import { currentEndpoint, normalizeLanUrl, saveEndpoint, testEndpoint } from "@/common/apiEndpoint";
|
||||
import { APP_INFO } from "@/common/constant";
|
||||
import { useAuthGuard, useThemeGradient, useThemeTokens } from "@/composables";
|
||||
import { usePermission } from "@/permission/permission-context";
|
||||
@@ -46,6 +47,63 @@ function goTheme(): void {
|
||||
uni.navigateTo({ url: pageUrl("themePage") });
|
||||
}
|
||||
|
||||
// ===== 访问线路(App 手动切换公网/内网直连;仅影响后续请求,不中断在途传输) =====
|
||||
const linePopupVisible = ref(false);
|
||||
/** 当前生效线路(保存后刷新展示) */
|
||||
const lineSetting = ref(currentEndpoint());
|
||||
/** 弹层草稿:确认前不动真实线路,取消即作废 */
|
||||
const lineModeDraft = ref<"wan" | "lan">("wan");
|
||||
const lineLanDraft = ref("");
|
||||
const lineTesting = ref(false);
|
||||
const lineTestResult = ref<"" | "ok" | "fail">("");
|
||||
|
||||
/** 当前线路展示文案:公网 / 内网直连(附地址) */
|
||||
const currentLineLabel = computed(() => {
|
||||
const setting = lineSetting.value;
|
||||
return setting.mode === "lan" ? `${t("MinePage.lineLan")} · ${setting.lanUrl}` : t("MinePage.lineWan");
|
||||
});
|
||||
|
||||
/** 打开线路弹层:草稿回填当前设置,清掉上次测活结果 */
|
||||
function openLinePopup(): void {
|
||||
const setting = currentEndpoint();
|
||||
lineModeDraft.value = setting.mode;
|
||||
lineLanDraft.value = setting.lanUrl;
|
||||
lineTestResult.value = "";
|
||||
linePopupVisible.value = true;
|
||||
}
|
||||
|
||||
/** 测试内网地址连通性:用 RSA 公钥接口探活(与登录首调同源) */
|
||||
async function handleTestLine(): Promise<void> {
|
||||
if (lineTesting.value) {
|
||||
return;
|
||||
}
|
||||
const url = normalizeLanUrl(lineLanDraft.value);
|
||||
if (!url) {
|
||||
uni.showToast({ title: t("MinePage.lineInvalid"), icon: "none" });
|
||||
return;
|
||||
}
|
||||
lineTesting.value = true;
|
||||
lineTestResult.value = "";
|
||||
const ok = await testEndpoint(url);
|
||||
lineTesting.value = false;
|
||||
lineTestResult.value = ok ? "ok" : "fail";
|
||||
if (!ok) {
|
||||
uni.showToast({ title: t("MinePage.lineTestFail"), icon: "none" });
|
||||
}
|
||||
}
|
||||
|
||||
/** 保存线路:内网模式地址必填且合法;生效只影响后续请求,各页切回时自然按新线路拉数据 */
|
||||
function handleSaveLine(): void {
|
||||
if (lineModeDraft.value === "lan" && !normalizeLanUrl(lineLanDraft.value)) {
|
||||
uni.showToast({ title: t("MinePage.lineInvalid"), icon: "none" });
|
||||
return;
|
||||
}
|
||||
saveEndpoint({ mode: lineModeDraft.value, lanUrl: lineLanDraft.value });
|
||||
lineSetting.value = currentEndpoint();
|
||||
linePopupVisible.value = false;
|
||||
uni.showToast({ title: t("MinePage.lineSaved"), icon: "none" });
|
||||
}
|
||||
|
||||
/** 进入「安全管理」枢纽页:权限体系等基础设定的聚合入口 */
|
||||
function goSecurity(): void {
|
||||
uni.navigateTo({ url: pageUrl("securityPage") });
|
||||
@@ -126,6 +184,22 @@ async function handleLogout(): Promise<void> {
|
||||
<u-icon name="arrow-right" size="32" color="#9aa0a6" />
|
||||
</view>
|
||||
|
||||
<!-- 访问线路:App 手动切换公网/内网直连(资源地址由后端按请求 Host 自适应,仅 App 展示) -->
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<view class="mine-cell" @tap="openLinePopup">
|
||||
<view class="mine-cell__icon">
|
||||
<u-icon name="server-man" size="30" color="#ffffff" />
|
||||
</view>
|
||||
<text class="mine-cell__title">
|
||||
{{ t("MinePage.accessLine") }}
|
||||
</text>
|
||||
<text class="mine-cell__value">
|
||||
{{ currentLineLabel }}
|
||||
</text>
|
||||
<u-icon name="arrow-right" size="32" color="#9aa0a6" />
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 安全管理:进入权限体系基础设定聚合页(/security) -->
|
||||
<view class="mine-cell" @tap="goSecurity">
|
||||
<view class="mine-cell__icon">
|
||||
@@ -240,6 +314,79 @@ async function handleLogout(): Promise<void> {
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 访问线路弹层:公网/内网单选 + 内网地址手填 + 测连通(仅 App 有入口) -->
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<u-popup :model-value="linePopupVisible" mode="bottom" round="24" @close="linePopupVisible = false">
|
||||
<view class="line-sheet">
|
||||
<text class="line-sheet__title">
|
||||
{{ t("MinePage.accessLine") }}
|
||||
</text>
|
||||
<text class="line-sheet__hint">
|
||||
{{ t("MinePage.lineHint") }}
|
||||
</text>
|
||||
|
||||
<!-- 公网:默认线路,随时随地可用 -->
|
||||
<view class="line-option" :class="{ 'line-option--active': lineModeDraft === 'wan' }"
|
||||
@tap="lineModeDraft = 'wan'">
|
||||
<view class="line-option__body">
|
||||
<text class="line-option__name">
|
||||
{{ t("MinePage.lineWan") }}
|
||||
</text>
|
||||
<text class="line-option__desc">
|
||||
{{ t("MinePage.lineWanDesc") }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="line-option__radio" :class="{ 'line-option__radio--on': lineModeDraft === 'wan' }" />
|
||||
</view>
|
||||
|
||||
<!-- 内网直连:需与服务器同局域网,地址手填 -->
|
||||
<view class="line-option" :class="{ 'line-option--active': lineModeDraft === 'lan' }"
|
||||
@tap="lineModeDraft = 'lan'">
|
||||
<view class="line-option__body">
|
||||
<text class="line-option__name">
|
||||
{{ t("MinePage.lineLan") }}
|
||||
</text>
|
||||
<text class="line-option__desc">
|
||||
{{ t("MinePage.lineLanDesc") }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="line-option__radio" :class="{ 'line-option__radio--on': lineModeDraft === 'lan' }" />
|
||||
</view>
|
||||
|
||||
<!-- 内网地址:选中内网才展开;测连通用免鉴权的 RSA 公钥接口 -->
|
||||
<view v-if="lineModeDraft === 'lan'" class="line-lan">
|
||||
<input v-model="lineLanDraft" class="line-lan__input" :placeholder="t('MinePage.lineLanPlaceholder')"
|
||||
placeholder-class="line-lan__ph">
|
||||
<view class="line-lan__test" @tap="handleTestLine">
|
||||
<text class="line-lan__test-text">
|
||||
{{ lineTesting ? t("MinePage.lineTesting") : t("MinePage.lineTest") }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<text v-if="lineModeDraft === 'lan' && lineTestResult === 'ok'" class="line-lan__result line-lan__result--ok">
|
||||
{{ t("MinePage.lineTestOk") }}
|
||||
</text>
|
||||
<text v-else-if="lineModeDraft === 'lan' && lineTestResult === 'fail'"
|
||||
class="line-lan__result line-lan__result--fail">
|
||||
{{ t("MinePage.lineTestFail") }}
|
||||
</text>
|
||||
|
||||
<view class="line-sheet__actions">
|
||||
<view class="line-sheet__btn line-sheet__btn--ghost" @tap="linePopupVisible = false">
|
||||
<text class="line-sheet__btn-text line-sheet__btn-text--ghost">
|
||||
{{ t("MinePage.lineCancel") }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="line-sheet__btn line-sheet__btn--primary" @tap="handleSaveLine">
|
||||
<text class="line-sheet__btn-text">
|
||||
{{ t("MinePage.lineSave") }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
<!-- #endif -->
|
||||
</app-page>
|
||||
</template>
|
||||
|
||||
@@ -356,4 +503,157 @@ async function handleLogout(): Promise<void> {
|
||||
font-size: 26rpx;
|
||||
color: #1f2329;
|
||||
}
|
||||
|
||||
/* ===== 访问线路弹层(底部抽屉,同 file-action-sheet 风格) ===== */
|
||||
.line-sheet {
|
||||
padding: 32rpx 24rpx calc(24rpx + env(safe-area-inset-bottom));
|
||||
background-color: #f5f6f7;
|
||||
}
|
||||
|
||||
.line-sheet__title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #1f2329;
|
||||
}
|
||||
|
||||
.line-sheet__hint {
|
||||
display: block;
|
||||
margin-top: 8rpx;
|
||||
font-size: 24rpx;
|
||||
color: #9aa0a6;
|
||||
}
|
||||
|
||||
/* 单选行:白卡;选中态用内阴影描边(不改变布局尺寸) */
|
||||
.line-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 20rpx;
|
||||
padding: 24rpx;
|
||||
border-radius: 20rpx;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.line-option--active {
|
||||
box-shadow: 0 0 0 2rpx var(--fg-primary, #ff7d1f) inset;
|
||||
}
|
||||
|
||||
.line-option__body {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
gap: 6rpx;
|
||||
}
|
||||
|
||||
.line-option__name {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #1f2329;
|
||||
}
|
||||
|
||||
.line-option__desc {
|
||||
font-size: 24rpx;
|
||||
color: #9aa0a6;
|
||||
}
|
||||
|
||||
.line-option__radio {
|
||||
box-sizing: border-box;
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin-left: 16rpx;
|
||||
border: 2rpx solid #d4d7dc;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.line-option__radio--on {
|
||||
border-color: var(--fg-primary, #ff7d1f);
|
||||
background: radial-gradient(circle, var(--fg-primary, #ff7d1f) 0 42%, transparent 48%);
|
||||
}
|
||||
|
||||
/* 内网地址:输入框 + 测试连接一行 */
|
||||
.line-lan {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.line-lan__input {
|
||||
flex: 1;
|
||||
height: 76rpx;
|
||||
padding: 0 20rpx;
|
||||
border-radius: 16rpx;
|
||||
font-size: 26rpx;
|
||||
color: #1f2329;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.line-lan__ph {
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.line-lan__test {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 76rpx;
|
||||
padding: 0 24rpx;
|
||||
border-radius: 16rpx;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.line-lan__test-text {
|
||||
font-size: 26rpx;
|
||||
font-weight: 600;
|
||||
color: var(--fg-primary, #ff7d1f);
|
||||
}
|
||||
|
||||
.line-lan__result {
|
||||
display: block;
|
||||
margin-top: 12rpx;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.line-lan__result--ok {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.line-lan__result--fail {
|
||||
color: #fa3534;
|
||||
}
|
||||
|
||||
/* 底部双按钮:取消(描边)/ 保存(主题渐变) */
|
||||
.line-sheet__actions {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
margin-top: 32rpx;
|
||||
}
|
||||
|
||||
.line-sheet__btn {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 88rpx;
|
||||
border-radius: 999rpx;
|
||||
}
|
||||
|
||||
.line-sheet__btn--ghost {
|
||||
border: 2rpx solid #d4d7dc;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.line-sheet__btn--primary {
|
||||
background: var(--fg-gradient, linear-gradient(135deg, #ff9a3d, #ff7d1f));
|
||||
box-shadow: var(--fg-shadow, 0 6rpx 16rpx rgba(255, 125, 31, 0.35));
|
||||
}
|
||||
|
||||
.line-sheet__btn-text {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.line-sheet__btn-text--ghost {
|
||||
color: #4e5969;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user