对接登录
This commit is contained in:
parent
408994e4f0
commit
f81afb3782
@ -1,11 +1,31 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref} from "vue";
|
import {ref} from "vue";
|
||||||
|
import {login} from "../../script/functions";
|
||||||
|
|
||||||
|
|
||||||
const showLoginDialog = ref(false)
|
const showLoginDialog = ref(false)
|
||||||
const username = ref('')
|
const username = ref('')
|
||||||
const password = ref('')
|
const password = ref('')
|
||||||
const passwordVisibleState = ref(false)
|
const passwordVisibleState = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const loginDisabled = ref(false)
|
||||||
|
const loginIcon = ref<any>(null)
|
||||||
|
|
||||||
|
async function tryLogin() {
|
||||||
|
loading.value = true
|
||||||
|
const isSuccess = await login(username.value, password.value)
|
||||||
|
if (isSuccess) {
|
||||||
|
loginIcon.value = "mdi-check"
|
||||||
|
loading.value = false
|
||||||
|
loginDisabled.value = true
|
||||||
|
setTimeout(() => {
|
||||||
|
showLoginDialog.value = false
|
||||||
|
}, 1000)
|
||||||
|
} else {
|
||||||
|
alert("login failed")
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -36,19 +56,30 @@ const passwordVisibleState = ref(false)
|
|||||||
</v-main>
|
</v-main>
|
||||||
</v-app>
|
</v-app>
|
||||||
</v-responsive>
|
</v-responsive>
|
||||||
<v-dialog v-model="showLoginDialog" persistent width="500">
|
<v-dialog v-model="showLoginDialog" persistent width="400">
|
||||||
<v-card prepend-icon="mdi-login" title="LOGIN" class="px-10">
|
<v-card prepend-icon="mdi-login" title="LOGIN" class="px-10">
|
||||||
<v-text-field class="login-dialong-input" flat prepend-icon="mdi-account" label="USERNAME" density="compact"
|
<v-text-field class="login-dialong-input" flat prepend-inner-icon="mdi-account-outline" label="USERNAME"
|
||||||
|
density="compact"
|
||||||
hide-details single-line rounded="lg" variant="solo-filled" v-model="username"></v-text-field>
|
hide-details single-line rounded="lg" variant="solo-filled" v-model="username"></v-text-field>
|
||||||
<v-text-field class="login-dialong-input" flat prepend-icon="mdi-lock" label="PASSWORD" density="compact"
|
<v-text-field class="login-dialong-input" flat prepend-inner-icon="mdi-lock-outline" label="PASSWORD"
|
||||||
hide-details single-line v-model="password" rounded="lg" variant="solo-filled"
|
density="compact" hide-details single-line v-model="password" rounded="lg" variant="solo-filled"
|
||||||
:type="passwordVisibleState ? 'text' :'password'" title="password"
|
:type="passwordVisibleState ? 'text' :'password'" title="password"
|
||||||
:append-inner-icon="passwordVisibleState ? 'mdi-eye-off' : 'mdi-eye'"
|
:append-inner-icon="passwordVisibleState ? 'mdi-eye-off' : 'mdi-eye'"
|
||||||
@click:append-inner="passwordVisibleState = !passwordVisibleState"></v-text-field>
|
@click:append-inner="passwordVisibleState = !passwordVisibleState"></v-text-field>
|
||||||
|
<v-card color="surface-variant" variant="tonal">
|
||||||
|
<v-card-text class="text-medium-emphasis text-caption">
|
||||||
|
PLEASE CONFIRM YOU HAVE READ AND AGREE TO THE
|
||||||
|
<v-label class="text-caption"><a href="javascript:void(0);">TERMS OF SERVICE</a></v-label>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
|
||||||
|
<v-checkbox class="login-dialong-input" label="Remember me" hide-details color="primary"></v-checkbox>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn text="CANCEL" @click="showLoginDialog = false"></v-btn>
|
<v-btn text="CANCEL" @click="showLoginDialog = false"></v-btn>
|
||||||
<v-btn color="primary" text="OK" @click="console.log(username, password)"></v-btn>
|
<v-btn :loading="loading" color="primary" text="LOGIN" @click="tryLogin()" :icon="loginIcon"
|
||||||
|
:disabled="loginDisabled">
|
||||||
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
@ -58,7 +89,8 @@ const passwordVisibleState = ref(false)
|
|||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-dialong-input {
|
.login-dialong-input {
|
||||||
margin-bottom: 10px;
|
margin: 10px 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -8,6 +8,7 @@ const slogans = [
|
|||||||
const show = ref("");
|
const show = ref("");
|
||||||
let c = 0, i = 0, showIndicator = ref(true);
|
let c = 0, i = 0, showIndicator = ref(true);
|
||||||
const showTimeout = 10000;
|
const showTimeout = 10000;
|
||||||
|
const printTime = 1000;
|
||||||
showSlogan(0)
|
showSlogan(0)
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
i++
|
i++
|
||||||
@ -18,7 +19,7 @@ setInterval(() => {
|
|||||||
|
|
||||||
function showSlogan(i: number) {
|
function showSlogan(i: number) {
|
||||||
const slogan = slogans[i]
|
const slogan = slogans[i]
|
||||||
const timeout = 2000 / slogan.length
|
const timeout = printTime / slogan.length
|
||||||
const handle = setInterval(() => {
|
const handle = setInterval(() => {
|
||||||
show.value = slogan.substring(0, c % slogan.length + 1);
|
show.value = slogan.substring(0, c % slogan.length + 1);
|
||||||
c++;
|
c++;
|
||||||
@ -30,7 +31,7 @@ function showSlogan(i: number) {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
clearInterval(indicatorHandle)
|
clearInterval(indicatorHandle)
|
||||||
showIndicator.value = true;
|
showIndicator.value = true;
|
||||||
}, showTimeout - 2000)
|
}, showTimeout - printTime)
|
||||||
}
|
}
|
||||||
}, timeout)
|
}, timeout)
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,44 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import {request} from "../../script/functions.ts";
|
||||||
|
import {ref} from "vue";
|
||||||
|
|
||||||
|
interface Urls {
|
||||||
|
key: string,
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Surls {
|
||||||
|
code: number,
|
||||||
|
msg?: string,
|
||||||
|
value?: Urls[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const urls = ref<Urls[]>([])
|
||||||
|
|
||||||
|
async function getSurl() {
|
||||||
|
const requestPromise = request('api/surl/get', {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer ' + localStorage.getItem('token') || ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
const request = await requestPromise
|
||||||
|
const body: Surls = await request.json()
|
||||||
|
urls.value = body.value ?? []
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-window></v-window>
|
<v-btn @click="getSurl">get</v-btn>
|
||||||
|
<ul>
|
||||||
|
<li v-for="url in urls">
|
||||||
|
<a :href="url.value">{{url.key}}: {{ url.value }}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
45
src/script/functions.ts
Normal file
45
src/script/functions.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import {useSiteConfigStore} from "../stores/siteconfig-store.ts";
|
||||||
|
import {useUserinfoStore} from "../stores/userinfo-store.ts";
|
||||||
|
|
||||||
|
interface LoginInfo {
|
||||||
|
code: number,
|
||||||
|
msg?: string,
|
||||||
|
value?: {
|
||||||
|
expireAt: string,
|
||||||
|
token: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function request(path: string, init: RequestInit): Promise<Response> {
|
||||||
|
const useSiteConfig = useSiteConfigStore()
|
||||||
|
const siteConfig = useSiteConfig.siteConfig
|
||||||
|
const protocol = siteConfig.protocol
|
||||||
|
const host = siteConfig.host
|
||||||
|
return fetch(`${protocol}://${host}/${path}`, init)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function login(username: string, password: string): Promise<boolean> {
|
||||||
|
const userinfoStore = useUserinfoStore()
|
||||||
|
const responsePromise = request('login', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({username, password}),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
mode: 'cors'
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
const response = await responsePromise
|
||||||
|
const body: LoginInfo = await response.json()
|
||||||
|
if(body.code == 0) {
|
||||||
|
userinfoStore.setToken(body.value?.token ?? '')
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { request, login }
|
14
src/stores/siteconfig-store.ts
Normal file
14
src/stores/siteconfig-store.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import {defineStore} from "pinia";
|
||||||
|
import {ref} from "vue";
|
||||||
|
interface SiteConfig {
|
||||||
|
protocol: string,
|
||||||
|
host: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSiteConfigStore = defineStore('siteConfigStore', ()=> {
|
||||||
|
const siteConfig = ref<SiteConfig>({
|
||||||
|
protocol: 'http',
|
||||||
|
host: 'localhost:18888'
|
||||||
|
})
|
||||||
|
return { siteConfig }
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user