mirror of
https://github.com/EasyTier/EasyTier.git
synced 2025-10-05 00:42:54 +08:00

Some checks failed
EasyTier Core / pre_job (push) Has been cancelled
EasyTier GUI / pre_job (push) Has been cancelled
EasyTier Mobile / pre_job (push) Has been cancelled
EasyTier Test / pre_job (push) Has been cancelled
EasyTier Core / build (freebsd-13.2-x86_64, 13.2, ubuntu-22.04, x86_64-unknown-freebsd) (push) Has been cancelled
EasyTier Core / build (linux-aarch64, ubuntu-22.04, aarch64-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-arm, ubuntu-22.04, arm-unknown-linux-musleabi) (push) Has been cancelled
EasyTier Core / build (linux-armhf, ubuntu-22.04, arm-unknown-linux-musleabihf) (push) Has been cancelled
EasyTier Core / build (linux-armv7, ubuntu-22.04, armv7-unknown-linux-musleabi) (push) Has been cancelled
EasyTier Core / build (linux-armv7hf, ubuntu-22.04, armv7-unknown-linux-musleabihf) (push) Has been cancelled
EasyTier Core / build (linux-mips, ubuntu-22.04, mips-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-mipsel, ubuntu-22.04, mipsel-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-x86_64, ubuntu-22.04, x86_64-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (macos-aarch64, macos-latest, aarch64-apple-darwin) (push) Has been cancelled
EasyTier Core / build (macos-x86_64, macos-latest, x86_64-apple-darwin) (push) Has been cancelled
EasyTier Core / build (windows-arm64, windows-latest, aarch64-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / build (windows-x86_64, windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / core-result (push) Has been cancelled
EasyTier GUI / build-gui (linux-aarch64, aarch64-unknown-linux-gnu, ubuntu-22.04, aarch64-unknown-linux-musl) (push) Has been cancelled
EasyTier GUI / build-gui (linux-x86_64, x86_64-unknown-linux-gnu, ubuntu-22.04, x86_64-unknown-linux-musl) (push) Has been cancelled
EasyTier GUI / build-gui (macos-aarch64, aarch64-apple-darwin, macos-latest, aarch64-apple-darwin) (push) Has been cancelled
EasyTier GUI / build-gui (macos-x86_64, x86_64-apple-darwin, macos-latest, x86_64-apple-darwin) (push) Has been cancelled
EasyTier GUI / build-gui (windows-arm64, aarch64-pc-windows-msvc, windows-latest, aarch64-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / build-gui (windows-x86_64, x86_64-pc-windows-msvc, windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / gui-result (push) Has been cancelled
EasyTier Mobile / build-mobile (android, ubuntu-22.04, android) (push) Has been cancelled
EasyTier Mobile / mobile-result (push) Has been cancelled
EasyTier Test / test (push) Has been cancelled
132 lines
5.7 KiB
Vue
132 lines
5.7 KiB
Vue
<script setup lang="ts">
|
|
import { computed, onMounted, ref } from 'vue';
|
|
import { Card, InputText, Password, Button, AutoComplete } from 'primevue';
|
|
import { useRouter } from 'vue-router';
|
|
import { useToast } from 'primevue/usetoast';
|
|
import { Api } from 'easytier-frontend-lib';
|
|
import {getInitialApiHost, cleanAndLoadApiHosts, saveApiHost} from "../modules/api-host"
|
|
|
|
defineProps<{
|
|
isRegistering: boolean;
|
|
}>();
|
|
|
|
const api = computed<Api.ApiClient>(() => new Api.ApiClient(apiHost.value));
|
|
const router = useRouter();
|
|
const toast = useToast();
|
|
|
|
const username = ref('');
|
|
const password = ref('');
|
|
const registerUsername = ref('');
|
|
const registerPassword = ref('');
|
|
const captcha = ref('');
|
|
const captchaSrc = computed(() => api.value.captcha_url());
|
|
|
|
|
|
const onSubmit = async () => {
|
|
// Add your login logic here
|
|
saveApiHost(apiHost.value);
|
|
const credential: Api.Credential = { username: username.value, password: password.value, };
|
|
let ret = await api.value?.login(credential);
|
|
if (ret.success) {
|
|
localStorage.setItem('apiHost', btoa(apiHost.value));
|
|
router.push({
|
|
name: 'dashboard',
|
|
params: { apiHost: btoa(apiHost.value) },
|
|
});
|
|
} else {
|
|
toast.add({ severity: 'error', summary: 'Login Failed', detail: ret.message, life: 2000 });
|
|
}
|
|
};
|
|
|
|
const onRegister = async () => {
|
|
saveApiHost(apiHost.value);
|
|
const credential: Api.Credential = { username: registerUsername.value, password: registerPassword.value };
|
|
const registerReq: Api.RegisterData = { credentials: credential, captcha: captcha.value };
|
|
let ret = await api.value?.register(registerReq);
|
|
if (ret.success) {
|
|
toast.add({ severity: 'success', summary: 'Register Success', detail: ret.message, life: 2000 });
|
|
router.push({ name: 'login' });
|
|
} else {
|
|
toast.add({ severity: 'error', summary: 'Register Failed', detail: ret.message, life: 2000 });
|
|
}
|
|
};
|
|
|
|
const apiHost = ref<string>(getInitialApiHost())
|
|
const apiHostSuggestions = ref<Array<string>>([])
|
|
const apiHostSearch = async (event: { query: string }) => {
|
|
apiHostSuggestions.value = [];
|
|
let hosts = cleanAndLoadApiHosts();
|
|
if (event.query) {
|
|
apiHostSuggestions.value.push(event.query);
|
|
}
|
|
hosts.forEach((host) => {
|
|
apiHostSuggestions.value.push(host.value);
|
|
});
|
|
}
|
|
|
|
onMounted(() => {
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex items-center justify-center min-h-screen">
|
|
<Card class="w-full max-w-md p-6">
|
|
<template #header>
|
|
<h2 class="text-2xl font-semibold text-center">{{ isRegistering ? 'Register' : 'Login' }}
|
|
</h2>
|
|
</template>
|
|
<template #content>
|
|
<div class="p-field mb-4">
|
|
<label for="api-host" class="block text-sm font-medium">Api Host</label>
|
|
<AutoComplete id="api-host" v-model="apiHost" dropdown :suggestions="apiHostSuggestions"
|
|
@complete="apiHostSearch" class="w-full" />
|
|
</div>
|
|
<form v-if="!isRegistering" @submit.prevent="onSubmit" class="space-y-4">
|
|
<div class="p-field">
|
|
<label for="username" class="block text-sm font-medium">Username</label>
|
|
<InputText id="username" v-model="username" required class="w-full" />
|
|
</div>
|
|
<div class="p-field">
|
|
<label for="password" class="block text-sm font-medium">Password</label>
|
|
<Password id="password" v-model="password" required toggleMask :feedback="false" />
|
|
</div>
|
|
<div class="flex items-center justify-between">
|
|
<Button label="Login" type="submit" class="w-full" />
|
|
</div>
|
|
<div class="flex items-center justify-between">
|
|
<Button label="Register" type="button" class="w-full"
|
|
@click="saveApiHost(apiHost); $router.replace({ name: 'register' })" severity="secondary" />
|
|
</div>
|
|
</form>
|
|
|
|
<form v-else @submit.prevent="onRegister" class="space-y-4">
|
|
<div class="p-field">
|
|
<label for="register-username" class="block text-sm font-medium">Username</label>
|
|
<InputText id="register-username" v-model="registerUsername" required class="w-full" />
|
|
</div>
|
|
<div class="p-field">
|
|
<label for="register-password" class="block text-sm font-medium">Password</label>
|
|
<Password id="register-password" v-model="registerPassword" required toggleMask
|
|
:feedback="false" class="w-full" />
|
|
</div>
|
|
<div class="p-field">
|
|
<label for="captcha" class="block text-sm font-medium">Captcha</label>
|
|
<InputText id="captcha" v-model="captcha" required class="w-full" />
|
|
<img :src="captchaSrc" alt="Captcha" class="mt-2 mb-2" />
|
|
</div>
|
|
<div class="flex items-center justify-between">
|
|
<Button label="Register" type="submit" class="w-full" />
|
|
</div>
|
|
<div class="flex items-center justify-between">
|
|
<Button label="Back to Login" type="button" class="w-full"
|
|
@click="saveApiHost(apiHost); $router.replace({ name: 'login' })" severity="secondary" />
|
|
</div>
|
|
</form>
|
|
</template>
|
|
</Card>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped></style> |