You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

240 lines
7.6 KiB

<template>
<q-layout
view="hhh lpr lff"
:style="{
'min-width': $gc.theme.minWidth + 'px',
'background-image': 'url(' + $gc.theme.login.bgImage + ')',
'background-position': 'center center',
'background-repeat': 'no-repeat',
'background-size': 'cover',
'background-attachment': 'fixed',
}"
>
<q-header>
<q-toolbar
:style="{
'min-width': $gc.theme.minWidth + 'px',
height: $gc.theme.topper.height + 'px',
color: $gc.theme.topper.color,
'background-color': $gc.theme.topper.bgColor,
}"
>
<!-- logo icon -->
<q-img
:src="$gc.theme.topper.logo"
:width="$gc.theme.topper.logoWidth + 'px'"
:height="$gc.theme.topper.logoHeight + 'px'"
:style="{
'min-width': $gc.theme.topper.logoWidth + 'px',
}"
/>
<!-- application name-->
<div
v-if="$gc.theme.topper.showTitle"
class="q-px-md text-h5"
:style="{
color: $gc.theme.topper.titleColor,
overflow: 'hidden',
'text-overflow': 'ellipsis',
'white-space': 'nowrap',
}"
>
{{ $t('application.title') }}
</div>
<!-- space -->
<q-space />
<!-- profile dropdown action-->
<q-btn stretch flat no-caps stack inline :title="$t('language')">
<div class="row items-center">
<q-icon left name="language" size="md" />
<div class="text-left">{{ $t('language') }}</div>
</div>
<q-menu>
<q-list>
<q-item v-for="lang in $gc.setting.i18n.availableLocales" :key="lang" v-close-popup clickable @click="changeLanguage(lang)">
<q-item-section>
<q-item-label>
{{ $t('language.' + lang) }}
</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</q-toolbar>
</q-header>
<q-page-container>
<div>
<div style="height: 100px"></div>
<div class="row">
<div class="col-xs-1 col-sm-5 col-md-7"></div>
<div class="col-xs-10 col-sm-6 col-md-4">
<q-form :action="gc.webContextPath + 'login'" method="post" @reset="loginFormReset" @submit.prevent="loginFormSubmit">
<q-card>
<q-item>
<q-item-section avatar>
<q-icon name="verified_user" size="50px" color="primary"> </q-icon>
</q-item-section>
<q-item-section>
<q-item-label class="text-h6">{{ $t('security.login.title') }}</q-item-label>
</q-item-section>
</q-item>
<q-separator />
<q-card-section v-if="$gc.loginError" class="q-px-lg">
<div class="row">
<div class="col-2 row justify-center items-center">
<q-icon name="warning" size="lg" color="negative" />
</div>
<div class="col-10 text-negative text-subtitle2 row justify-start items-center">
{{ $t('security.login.message.error') }}
</div>
</div>
</q-card-section>
<q-card-section class="q-px-lg">
<q-input
v-model="username"
name="username"
outlined
:label="$t('security.login.username.placeholder')"
autofocus
clearable
tabindex="1"
hint=""
lazy-rules
:rules="[(val: any) => (val && val.length > 0) || '']"
>
<template #before>
<q-icon name="account_circle" size="40px" color="secondary" />
</template>
</q-input>
<q-input
v-model="password"
name="password"
:type="isPassword ? 'password' : 'text'"
autocomplete="false"
outlined
:label="$t('security.login.password.placeholder')"
clearable
tabindex="2"
lazy-rules
:rules="[(val: any) => (val && val.length > 0) || '']"
>
<template #before>
<q-icon name="key" size="40px" color="secondary" />
</template>
<template #append>
<q-icon :name="isPassword ? 'visibility_off' : 'visibility'" class="cursor-pointer" @click="isPassword = !isPassword" />
</template>
</q-input>
</q-card-section>
<q-card-actions align="right" class="q-px-lg">
<div class="q-gutter-md">
<q-btn type="submit" :label="$t('login')" no-caps rounded color="primary" tabindex="3" style="width: 100px"> </q-btn>
<q-btn type="reset" :label="$t('reset')" no-caps rounded color="secondary" tabindex="4" style="width: 100px"></q-btn>
</div>
</q-card-actions>
<q-card-actions align="right" class="q-px-md"> </q-card-actions>
</q-card>
</q-form>
</div>
<div class="col-1"></div>
</div>
</div>
</q-page-container>
<q-footer v-if="$gc.theme.footer.show">
<div
class="row justify-center items-center"
:style="{
height: $gc.theme.footer.height + 'px',
color: $gc.theme.footer.color,
'background-color': $gc.theme.footer.bgColor,
}"
>
<div>{{ $t('application.copyright') }}</div>
</div>
</q-footer>
</q-layout>
</template>
<script setup lang="ts">
import { ref, nextTick } from 'vue';
import { useQuasar, dom } from 'quasar';
import { gc, i18n } from './plugin';
const quasar = useQuasar();
const { ready } = dom;
const username = ref('');
const password = ref('');
const isPassword = ref(true);
const changeLanguage = (locale) => {
i18n.global.locale.value = locale;
setTitile(i18n.global.t('application.title'));
};
const loginFormReset = () => {
username.value = '';
password.value = '';
};
const loginFormSubmit = (event) => {
if (gc.theme.login.encodePassword) {
password.value = encodeBase64(password.value);
nextTick(() => {
event.target.submit();
});
} else {
event.target.submit();
}
};
const encodeBase64 = (text: string): string => {
return '{BASE64}' + window.btoa(encodeURIComponent(text));
};
/**
* 设置页面标题
* @param title 页面标题
*/
const setTitile = (title) => {
if (title) {
document.title = title;
}
};
/**
* 设置页面 icon
* @param iconUrl 页面 icon url 地址
*/
const setFavicon = (favicon) => {
if (favicon) {
let faviconElement: HTMLLinkElement = document.querySelector("link[rel*='icon']") as HTMLLinkElement;
if (faviconElement) {
console.log(faviconElement.href);
faviconElement.href = favicon;
} else {
faviconElement = document.createElement('link');
faviconElement.rel = 'shortcut icon';
faviconElement.href = favicon;
document.getElementsByTagName('head')[0].appendChild(faviconElement);
}
}
};
ready(function () {
setTitile(i18n.global.t('application.title'));
setFavicon(gc.theme.favicon);
quasar?.dark?.set(gc.theme.dark);
});
</script>