This commit is contained in:
che
2026-07-26 20:30:38 +05:00
parent 1441a14b90
commit 560b3fe44e
12 changed files with 908 additions and 271 deletions
+8
View File
@@ -0,0 +1,8 @@
import SettingsView from "./views/SettingsView.vue";
export const settingsRoute = {
path: "/settings",
name: "settings",
component: SettingsView,
meta: { title: "Настройки" },
};
+160
View File
@@ -0,0 +1,160 @@
<script setup lang="ts">
import { invoke } from "@tauri-apps/api/core";
import { onMounted, reactive, ref } from "vue";
import { useRouter } from "vue-router";
import { showToast } from "vant";
import { clearAuthState } from "../../../shared/auth/useAuth";
interface AppSettings {
remote_base_url: string;
auth_path: string;
}
const router = useRouter();
const loading = ref(false);
const saving = ref(false);
const error = ref("");
const settings = reactive<AppSettings>({
remote_base_url: "",
auth_path: "/api-token-auth/",
});
onMounted(loadSettings);
async function loadSettings() {
loading.value = true;
error.value = "";
try {
applySettings(await invoke<AppSettings>("get_app_settings"));
} catch (err) {
error.value = errorMessage(err, "Не удалось загрузить настройки");
} finally {
loading.value = false;
}
}
async function saveSettings() {
saving.value = true;
error.value = "";
try {
const saved = await invoke<AppSettings>("update_app_settings", {
settings: {
remote_base_url: settings.remote_base_url,
auth_path: settings.auth_path,
},
});
applySettings(saved);
clearAuthState();
showToast("Настройки сохранены. Войдите заново");
router.replace("/login");
} catch (err) {
error.value = errorMessage(err, "Не удалось сохранить настройки");
} finally {
saving.value = false;
}
}
async function resetSettings() {
saving.value = true;
error.value = "";
try {
applySettings(await invoke<AppSettings>("reset_app_settings"));
clearAuthState();
showToast("Настройки сброшены. Войдите заново");
router.replace("/login");
} catch (err) {
error.value = errorMessage(err, "Не удалось сбросить настройки");
} finally {
saving.value = false;
}
}
function applySettings(nextSettings: AppSettings) {
settings.remote_base_url = nextSettings.remote_base_url;
settings.auth_path = nextSettings.auth_path;
}
function errorMessage(err: unknown, fallback: string) {
if (typeof err === "object" && err && "detail" in err) {
return String((err as { detail: unknown }).detail);
}
if (err instanceof Error) {
return err.message;
}
return fallback;
}
</script>
<template>
<van-notice-bar
v-if="error"
class="notice"
color="#991b1b"
background="#fee2e2"
left-icon="warning-o"
wrapable
:scrollable="false"
:text="error"
/>
<van-form class="card" @submit="saveSettings">
<van-loading v-if="loading" class="state" type="spinner">Загрузка...</van-loading>
<template v-else>
<van-field
v-model="settings.remote_base_url"
name="remote_base_url"
label="Удаленный URL"
placeholder="http://10.0.2.2:8000"
clearable
:disabled="saving"
:rules="[{ required: true, message: 'Введите URL сервера' }]"
/>
<van-field
v-model="settings.auth_path"
name="auth_path"
label="Auth path"
placeholder="/api-token-auth/"
clearable
:disabled="saving"
:rules="[{ required: true, message: 'Введите путь авторизации' }]"
/>
<div class="settings-help">
Для Android-эмулятора сервер на хосте обычно доступен как
<code>http://10.0.2.2:8000</code>.
</div>
<div class="form-actions stacked-actions">
<van-button block round type="primary" native-type="submit" :loading="saving">
Сохранить
</van-button>
<van-button
block
round
type="default"
native-type="button"
plain
:disabled="saving"
@click="resetSettings"
>
Сбросить по умолчанию
</van-button>
</div>
</template>
</van-form>
</template>
<style scoped>
.settings-help {
padding: 12px 16px 0;
color: #64748b;
font-size: 13px;
line-height: 1.5;
}
</style>