update ConnectSetting.vue

This commit is contained in:
Timi
2026-04-13 16:11:37 +08:00
parent a6c89717a6
commit 753ab56e06
8 changed files with 155 additions and 165 deletions

View File

@@ -5,9 +5,14 @@
v-if="navBarStore.isShowing" v-if="navBarStore.isShowing"
class="nav-bar" class="nav-bar"
:title="navBarStore.title" :title="navBarStore.title"
:left-arrow="!!navBarStore.canBack" :left-arrow="!hasCustomLeft && !!navBarStore.canBack"
@left-click="doBack" @left-click="onLeftClick"
> >
<template v-if="hasCustomLeft" #left>
<div class="nav-extra nav-extra-left">
<component :is="navBarStore.leftRenderer" />
</div>
</template>
<template #right> <template #right>
<div class="nav-extra"> <div class="nav-extra">
<component :is="navBarStore.rightRenderer" v-if="navBarStore.rightRenderer" /> <component :is="navBarStore.rightRenderer" v-if="navBarStore.rightRenderer" />
@@ -80,6 +85,8 @@ onUnmounted(() => {
// ---------- 导航返回 ---------- // ---------- 导航返回 ----------
const hasCustomLeft = computed(() => !!navBarStore.leftRenderer);
function doBack(): void { function doBack(): void {
if (navBarStore.backTo) { if (navBarStore.backTo) {
router.push(navBarStore.backTo); router.push(navBarStore.backTo);
@@ -89,6 +96,14 @@ function doBack(): void {
} }
} }
function onLeftClick(): void {
if (hasCustomLeft.value) {
return;
}
doBack();
}
const navBarPadding = computed(() => { const navBarPadding = computed(() => {
if (navBarStore.isShowing) { if (navBarStore.isShowing) {
return `${navBarStore.height || 48}px`; return `${navBarStore.height || 48}px`;
@@ -202,6 +217,10 @@ const contentHeight = computed(() => {
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
} }
.nav-extra-left {
justify-content: flex-start;
}
} }
.router-view { .router-view {

View File

@@ -393,10 +393,4 @@ function getDirectoryKey(pathSegments: string[]): string {
font-size: .8125rem; font-size: .8125rem;
} }
} }
:global(.theme-dark) .page {
.go-up {
box-shadow: 0 .35rem 1rem rgba(0, 0, 0, .22);
}
}
</style> </style>

View File

@@ -1,103 +1,84 @@
<template> <template>
<div class="page"> <div class="connect-setting">
<section class="card"> <t-cell-group title="服务器连接" theme="card">
<div class="head"> <t-cell title="使用 HTTPS">
<p class="tag">连接配置</p> <template #rightIcon>
<h2 class="header">服务器连接</h2> <t-switch v-model="httpsEnabled" />
<p class="desc">这里的配置会持久化保存缺失时应用会强制回到连接引导页</p> </template>
</div> </t-cell>
<t-input
<div class="group"> v-model.trim="form.host"
<p class="label">协议</p> clearable
<div class="protocols"> label="地址"
<t-button placeholder="192.168.1.10 或 nas.local"
size="small" />
theme="primary" <t-input
:variant="form.protocol === 'http' ? 'base' : 'outline'" v-model.trim="form.port"
@click="setProtocol('http')" clearable
> label="端口"
HTTP placeholder="8080"
</t-button> type="number"
<t-button />
size="small" <t-input
theme="primary" v-model.trim="form.token"
:variant="form.protocol === 'https' ? 'base' : 'outline'" clearable
@click="setProtocol('https')" label="密钥"
> placeholder="请输入访问密钥"
HTTPS />
</t-button> </t-cell-group>
</div>
</div>
<div class="group">
<p class="label">主机地址</p>
<t-input v-model="form.host" clearable placeholder="例如 192.168.1.100 或 nas.local" />
</div>
<div class="group">
<p class="label">端口</p>
<t-input v-model="form.port" clearable type="number" placeholder="例如 8080" />
</div>
<div class="group">
<p class="label">访问令牌</p>
<t-input v-model="form.token" clearable placeholder="请输入 token" />
</div>
<t-button block theme="primary" @click="saveConnect">
保存连接配置
</t-button>
<t-button block variant="outline" @click="resetConnect">
清空连接配置
</t-button>
</section>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Toast } from "tdesign-mobile-vue"; import { Toast } from "tdesign-mobile-vue";
import type { ConnectProtocol, ConnectSetting } from "@/store/settingStore"; import { useNavBarStore } from "@/store/navBarStore";
import type { ConnectSetting } from "@/store/settingStore";
import { useSettingStore } from "@/store/settingStore"; import { useSettingStore } from "@/store/settingStore";
defineOptions({ defineOptions({
name: "ConnectSetting" name: "ConnectSetting"
}); });
const router = useRouter();
const navBarStore = useNavBarStore();
const settingStore = useSettingStore(); const settingStore = useSettingStore();
const form = reactive<ConnectSetting>({ // ---------- 顶部导航 ----------
protocol: "http",
host: "", const navBarOwner = `connect-setting-${Math.random().toString(36).slice(2)}`;
port: "",
token: "" const navBarLeftRenderer = defineComponent({
name: "connect-setting-nav-left",
setup() {
const buttonComponent = resolveComponent("t-button");
return () => h(buttonComponent, {
variant: "text",
theme: "default",
size: "small",
onClick: cancelConnect
}, () => "取消");
}
}); });
watch( const navBarRightRenderer = defineComponent({
() => settingStore.connect, name: "connect-setting-nav-right",
(connect) => { setup() {
Object.assign(form, connect); const buttonComponent = resolveComponent("t-button");
},
{ immediate: true }
);
function setProtocol(protocol: ConnectProtocol): void { return () => h(buttonComponent, {
form.protocol = protocol; variant: "text",
theme: "primary",
size: "small",
onClick: saveConnect
}, () => "保存");
} }
function validateConnect(): boolean {
const host = form.host.trim();
const port = form.port.trim();
const token = form.token.trim();
if (!host || !port || !token) {
Toast({
theme: "warning",
message: "请完整填写连接配置"
}); });
return false;
}
return true; function cancelConnect(): void {
Object.assign(form, settingStore.connect);
router.back();
} }
function saveConnect(): void { function saveConnect(): void {
@@ -112,69 +93,57 @@ function saveConnect(): void {
}); });
} }
function resetConnect(): void { onMounted(() => {
settingStore.resetConnect(); navBarStore.setLeftRenderer(navBarLeftRenderer, navBarOwner);
Object.assign(form, settingStore.connect); navBarStore.setRightRenderer(navBarRightRenderer, navBarOwner);
Toast({
theme: "success",
message: "连接配置已清空"
}); });
onUnmounted(() => {
navBarStore.clearLeft(navBarOwner);
navBarStore.clearRight(navBarOwner);
});
// ---------- 表单 ----------
const form = reactive<ConnectSetting>({
protocol: "http",
host: "",
port: "",
token: ""
});
watch(() => settingStore.connect, (connect) => {
Object.assign(form, connect);
}, { immediate: true });
const httpsEnabled = computed({
get: () => form.protocol === "https",
set: (value: boolean) => {
form.protocol = value ? "https" : "http";
}
});
function validateConnect(): boolean {
const host = form.host.trim();
const port = form.port.trim();
const token = form.token.trim();
if (!host || !port || !token) {
Toast({
theme: "warning",
message: "请完整填写连接配置"
});
return false;
}
return true;
} }
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.page { .connect-setting {
padding: 1rem; padding-top: var(--app-nav-offset);
.card { :deep(.t-input:last-child:after) {
gap: 1rem; background: transparent;
display: flex;
padding: 1rem;
border-radius: 1rem;
flex-direction: column;
border: 1px solid var(--app-line);
background: var(--app-card);
box-shadow: 0 .35rem 1rem rgba(17, 32, 56, .05);
}
.head,
.group {
gap: .5rem;
display: flex;
flex-direction: column;
}
.tag,
.label,
.desc {
margin: 0;
color: var(--app-sub);
}
.tag,
.label {
font-size: .875rem;
}
.header {
margin: 0;
font-size: 1.25rem;
}
.desc {
line-height: 1.6;
}
.protocols {
gap: .75rem;
display: flex;
flex-wrap: wrap;
}
}
:global(.theme-dark) .page {
.card {
box-shadow: 0 .35rem 1rem rgba(0, 0, 0, .2);
} }
} }
</style> </style>

View File

@@ -256,10 +256,4 @@ function normalizeSecondValue(value: string, fallback: number): number {
flex-wrap: wrap; flex-wrap: wrap;
} }
} }
:global(.theme-dark) .page {
.card {
box-shadow: 0 .35rem 1rem rgba(0, 0, 0, .2);
}
}
</style> </style>

View File

@@ -84,10 +84,4 @@ const themeModeList: Array<{ label: string; value: ThemeMode }> = [
flex-wrap: wrap; flex-wrap: wrap;
} }
} }
:global(.theme-dark) .page {
.card {
box-shadow: 0 .35rem 1rem rgba(0, 0, 0, .2);
}
}
</style> </style>

View File

@@ -1,5 +1,5 @@
<template> <template>
<div class="page"> <div class="connect-setting">
<section class="card"> <section class="card">
<div class="head"> <div class="head">
<p class="tag">系统设置</p> <p class="tag">系统设置</p>
@@ -42,7 +42,7 @@ function openThemeSetting(): void {
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.page { .connect-setting {
gap: 1rem; gap: 1rem;
display: flex; display: flex;
padding: 1rem; padding: 1rem;
@@ -91,7 +91,7 @@ function openThemeSetting(): void {
} }
} }
:global(.theme-dark) .page { :global(.theme-dark) .connect-setting {
.card { .card {
box-shadow: 0 .35rem 1rem rgba(0, 0, 0, .2); box-shadow: 0 .35rem 1rem rgba(0, 0, 0, .2);
} }

View File

@@ -131,7 +131,8 @@ const router = createRouter({
navBarVisible: true, navBarVisible: true,
navBarCanBack: true, navBarCanBack: true,
navBarTitle: "连接配置", navBarTitle: "连接配置",
tabBarVisible: false tabBarVisible: false,
bodyBackground: "#F4F4F4"
}, },
component: ConnectSetting component: ConnectSetting
}, },

View File

@@ -8,6 +8,8 @@ export const useNavBarStore = defineStore("nav-bar", () => {
const height = ref(0); const height = ref(0);
const title = ref(""); const title = ref("");
const backTo = ref<string>(); const backTo = ref<string>();
const leftRenderer = shallowRef<Component>();
const leftOwner = ref<string>();
const rightRenderer = shallowRef<Component>(); const rightRenderer = shallowRef<Component>();
const rightOwner = ref<string>(); const rightOwner = ref<string>();
@@ -34,6 +36,20 @@ export const useNavBarStore = defineStore("nav-bar", () => {
title.value = value || ""; title.value = value || "";
} }
function setLeftRenderer(renderer?: Component, owner?: string): void {
leftRenderer.value = renderer;
leftOwner.value = owner;
}
function clearLeft(owner?: string): void {
if (owner && leftOwner.value !== owner) {
return;
}
leftRenderer.value = undefined;
leftOwner.value = undefined;
}
function setRightRenderer(renderer?: Component, owner?: string): void { function setRightRenderer(renderer?: Component, owner?: string): void {
rightRenderer.value = renderer; rightRenderer.value = renderer;
rightOwner.value = owner; rightOwner.value = owner;
@@ -52,12 +68,15 @@ export const useNavBarStore = defineStore("nav-bar", () => {
height, height,
title, title,
backTo, backTo,
leftRenderer,
rightRenderer, rightRenderer,
isShowing, isShowing,
canBack, canBack,
setHeight, setHeight,
setBackTo, setBackTo,
setTitle, setTitle,
setLeftRenderer,
clearLeft,
setRightRenderer, setRightRenderer,
clearRight clearRight
}; };