161 lines
4.1 KiB
Vue
161 lines
4.1 KiB
Vue
<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>
|