Update Lang
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
// Import Bulma's core
|
// Import Bulma's core
|
||||||
@import "~bulma/sass/utilities/_all";
|
@import "~bulma/sass/utilities/_all";
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900');
|
||||||
|
|
||||||
// Set your colors
|
// Set your colors
|
||||||
$primary: #107FFB; // #4285F4; // #0F9D58; // #009047;
|
$primary: #107FFB; // #4285F4; // #0F9D58; // #009047;
|
||||||
@@ -10,7 +11,7 @@ $findata: #ff8829; //#F4F7F8;
|
|||||||
$findata-invert: findColorInvert($findata);
|
$findata-invert: findColorInvert($findata);
|
||||||
$sidebar-width: 35%;
|
$sidebar-width: 35%;
|
||||||
//$family-primary: 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
//$family-primary: 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||||
$family-primary: Arial, sans-serif;
|
$family-primary: 'Inter', 'SF Pro', 'Helvetica', 'Arial', sans-serif;
|
||||||
|
|
||||||
// Setup $colors to use as bulma classes (e.g. 'is-twitter')s
|
// Setup $colors to use as bulma classes (e.g. 'is-twitter')s
|
||||||
$colors: (
|
$colors: (
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<span :class="`icon-text fsb-${size||17} ${type || 'has-text-findata'}`">
|
<span :class="`icon-text fsb-${size||17} ${type || 'has-text-findata'}`" class ="field is-align-items-center">
|
||||||
<b class="mr-1">{{ title }}</b>
|
<b class="mr-1">{{ title }}</b>
|
||||||
<SvgIcon v-bind="{name: 'right.svg', type: type? type.replace('has-text-', '') : null, size: (size>=30? size*0.7 : size) || 20, alt: 'Arrow'}"></SvgIcon>
|
<SvgIcon v-bind="{name: 'right.svg', type: type? type.replace('has-text-', '') : null, size: (size>=30? size*0.7 : size) || 20, alt: 'Arrow'}"></SvgIcon>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<div class="hero-body px-2 py-5">
|
<div class="hero-body px-2 py-5">
|
||||||
<article class="message is-primary">
|
<article class="message is-primary">
|
||||||
<div class="message-body has-text-black fs-16 py-3">
|
<div class="message-body has-text-black fs-16 py-3">
|
||||||
If you forgot your password, please contact your manager for assistance with password recovery.
|
{{ isVietnamese ? 'Trường hợp quên mật khẩu, vui lòng liên hệ với quản lý để được hỗ trợ khôi phục mật khẩu.' : 'If you have forgotten your password, please contact your manager for assistance with resetting your password.' }}
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
@@ -15,5 +15,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
export default {}
|
export default {
|
||||||
|
computed: {
|
||||||
|
isVietnamese() {
|
||||||
|
return navigator.language.toLowerCase().startsWith('vi');
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
363
pages/signin.vue
363
pages/signin.vue
@@ -1,62 +1,88 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="columns is-centered px-0 mx-0">
|
<div class="columns is-centered px-0 mx-0">
|
||||||
<div :class="`column is-${viewport>=4? 4 : 6}`">
|
<div
|
||||||
<div class="has-background-white px-6 py-6 mt-6">
|
:class="`column is-flex is-justify-content-center is-align-items-center wrapper-login is-${
|
||||||
<Logo />
|
viewport >= 4 ? 4 : 6
|
||||||
<Caption :class="`mt-5 pt-${viewport===1? 0 : 3}`" v-bind="{title: 'Sign in', size: 19}"></Caption>
|
}`"
|
||||||
<div class="field mt-5">
|
>
|
||||||
<label class="label">User name<b class="ml-1 has-text-danger">*</b></label>
|
<div class="has-background-white px-6 py-6 login-box">
|
||||||
<div class="control">
|
<Logo />
|
||||||
<input class="input" type="text" placeholder v-model="username" />
|
<Caption
|
||||||
</div>
|
:class="`mt-5 pt-${viewport === 1 ? 0 : 3}`"
|
||||||
<p
|
v-bind="{ title: `${isVietnamese ? 'Đăng nhập' : 'Login'}`, size: 19 }"
|
||||||
class="help is-danger"
|
></Caption>
|
||||||
v-if="errors.find(v=>v.name==='username')"
|
<div class="field mt-5">
|
||||||
v-html="errors.find(v=>v.name==='username').text"></p>
|
<label class="label"
|
||||||
|
>{{ isVietnamese ? 'Tên đăng nhập' : 'User name' }}<b class="ml-1 has-text-danger">*</b></label
|
||||||
|
>
|
||||||
|
<div class="control">
|
||||||
|
<input
|
||||||
|
class="input"
|
||||||
|
type="text"
|
||||||
|
:placeholder="isVietnamese ? 'Nhập tên đăng nhập' : 'Enter username'"
|
||||||
|
v-model="username"
|
||||||
|
@keyup.enter="signin()"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="field mt-5">
|
<p
|
||||||
<label class="label">Password<b class="ml-1 has-text-danger">*</b></label>
|
class="help is-danger"
|
||||||
<div class="field-body">
|
v-if="errors.find((v) => v.name === 'username')"
|
||||||
<div class="field has-addons">
|
v-html="errors.find((v) => v.name === 'username').text"
|
||||||
<p class="control is-expanded">
|
></p>
|
||||||
<input
|
</div>
|
||||||
class="input"
|
<div class="field mt-5">
|
||||||
:type="showpass? 'text' : 'password'"
|
<label class="label">{{ isVietnamese ? 'Mật khẩu' : 'Password' }}<b class="ml-1 has-text-danger">*</b></label>
|
||||||
placeholder
|
<div class="field-body">
|
||||||
v-model="password"
|
<div class="field has-addons">
|
||||||
/>
|
<p class="control is-expanded">
|
||||||
</p>
|
<input
|
||||||
<div class="control">
|
class="input"
|
||||||
<a class="button" @click="showpass=!showpass">
|
:type="showpass ? 'text' : 'password'"
|
||||||
<span class="icon">
|
:placeholder="isVietnamese ? 'Nhập mật khẩu' : 'Enter password'"
|
||||||
<SvgIcon v-bind="{name: showpass? 'eye-off.svg' : 'view.svg', type: 'gray'}"/>
|
v-model="password"
|
||||||
</span>
|
@keyup.enter="signin()"
|
||||||
</a>
|
/>
|
||||||
</div>
|
</p>
|
||||||
|
<div class="control">
|
||||||
|
<a
|
||||||
|
class="button"
|
||||||
|
@click="showpass = !showpass"
|
||||||
|
:title="
|
||||||
|
showpass ? (isVietnamese ? 'Đăng nhập' : 'Login') : isVietnamese ? 'Hiện mật khẩu' : 'Show Password'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<span class="icon">
|
||||||
|
<SvgIcon v-bind="{ name: showpass ? 'eye-off.svg' : 'view.svg', type: 'gray' }" />
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p
|
|
||||||
class="help is-danger"
|
|
||||||
v-if="errors.find(v=>v.name==='password')"
|
|
||||||
>{{errors.find(v=>v.name==='password').text}}</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="field is-grouped mt-5">
|
<p class="help is-danger" v-if="errors.find((v) => v.name === 'password')">
|
||||||
<div class="control is-expanded">
|
{{ errors.find((v) => v.name === 'password').text }}
|
||||||
<button class="button is-primary" @click="signin()">Login</button>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<div class="field is-grouped mt-5 is-align-items-center">
|
||||||
<a class="is-primary" @click="accountRecovery()">Forgot Password?</a>
|
<div class="control is-expanded">
|
||||||
</div>
|
<button class="button is-primary" @click="signin()" @keyup.enter="signin()">
|
||||||
|
{{ isVietnamese ? 'Đăng nhập' : 'Login' }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<a class="is-primary" @click="accountRecovery()"
|
||||||
|
>{{ isVietnamese ? 'Đặt lại mật khẩu' : 'Forgot Password' }}?</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import Bowser from "bowser"
|
import Bowser from 'bowser';
|
||||||
export default {
|
export default {
|
||||||
head() {
|
head() {
|
||||||
return {title: 'Signin'}
|
return { title: this.isVietnamese ? 'Đăng nhập' : 'Login' };
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -69,145 +95,216 @@ export default {
|
|||||||
type: undefined,
|
type: undefined,
|
||||||
isLoaded: false,
|
isLoaded: false,
|
||||||
data: undefined,
|
data: undefined,
|
||||||
account: undefined
|
account: undefined,
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
window.addEventListener("keyup", (ev) => ev.key==='Enter' && this.$route.name==='signup'? this.signin() : false)
|
window.addEventListener('keyup', (ev) =>
|
||||||
if(!this.module) return this.$router.push('/welcome')
|
ev.key === 'Enter' && this.$route.name === 'signup' ? this.signin() : false,
|
||||||
|
);
|
||||||
|
if (!this.module) return this.$router.push('/welcome');
|
||||||
|
|
||||||
|
console.log('this.$route.query', this.$route.query);
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
login: {
|
login: {
|
||||||
get: function() {return this.$store.state.login},
|
get: function () {
|
||||||
set: function(val) {this.$store.commit('updateLogin', {login: val})}
|
return this.$store.state.login;
|
||||||
|
},
|
||||||
|
set: function (val) {
|
||||||
|
this.$store.commit('updateLogin', { login: val });
|
||||||
|
},
|
||||||
},
|
},
|
||||||
registermethod: {
|
registermethod: {
|
||||||
get: function() {return this.$store.state.registermethod},
|
get: function () {
|
||||||
set: function(val) {this.$store.commit("updateRegisterMethod", {registermethod: val})}
|
return this.$store.state.registermethod;
|
||||||
|
},
|
||||||
|
set: function (val) {
|
||||||
|
this.$store.commit('updateRegisterMethod', { registermethod: val });
|
||||||
|
},
|
||||||
},
|
},
|
||||||
authmethod: {
|
authmethod: {
|
||||||
get: function() {return this.$store.state.authmethod},
|
get: function () {
|
||||||
set: function(val) {this.$store.commit("updateAuthMethod", {authmethod: val})}
|
return this.$store.state.authmethod;
|
||||||
|
},
|
||||||
|
set: function (val) {
|
||||||
|
this.$store.commit('updateAuthMethod', { authmethod: val });
|
||||||
|
},
|
||||||
},
|
},
|
||||||
authstatus: {
|
authstatus: {
|
||||||
get: function() {return this.$store.state.authstatus},
|
get: function () {
|
||||||
set: function(val) {this.$store.commit("updateAuthStatus", {authstatus: val})}
|
return this.$store.state.authstatus;
|
||||||
|
},
|
||||||
|
set: function (val) {
|
||||||
|
this.$store.commit('updateAuthStatus', { authstatus: val });
|
||||||
|
},
|
||||||
},
|
},
|
||||||
usertype: {
|
usertype: {
|
||||||
get: function() {return this.$store.state.usertype},
|
get: function () {
|
||||||
set: function(val) {this.$store.commit("updateUserType", {usertype: val})}
|
return this.$store.state.usertype;
|
||||||
|
},
|
||||||
|
set: function (val) {
|
||||||
|
this.$store.commit('updateUserType', { usertype: val });
|
||||||
|
},
|
||||||
},
|
},
|
||||||
viewport: {
|
viewport: {
|
||||||
get: function() {return this.$store.state.viewport},
|
get: function () {
|
||||||
set: function(val) {this.$store.commit("updateViewPort", {viewport: val})}
|
return this.$store.state.viewport;
|
||||||
|
},
|
||||||
|
set: function (val) {
|
||||||
|
this.$store.commit('updateViewPort', { viewport: val });
|
||||||
|
},
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
get: function() {return this.$store.state['module']},
|
get: function () {
|
||||||
set: function(val) {this.$store.commit('updateStore', {name: 'module', data: val})}
|
return this.$store.state['module'];
|
||||||
}
|
},
|
||||||
|
set: function (val) {
|
||||||
|
this.$store.commit('updateStore', { name: 'module', data: val });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
isVietnamese() {
|
||||||
|
return navigator.language.toLowerCase().startsWith('vi');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
checkError() {
|
checkError() {
|
||||||
this.errors = []
|
this.errors = [];
|
||||||
if (!this.$empty(this.username)) {
|
if (!this.$empty(this.username)) {
|
||||||
this.username = this.username.trim().toLowerCase();
|
this.username = this.username.trim().toLowerCase();
|
||||||
}
|
}
|
||||||
if (this.$empty(this.username)) {
|
if (this.$empty(this.username)) {
|
||||||
this.errors.push({
|
this.errors.push({
|
||||||
name: "username",
|
name: 'username',
|
||||||
text: "Email không được bỏ trống."
|
text: this.isVietnamese ? 'Tên đăng nhập không được bỏ trống.' : 'Username is required.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (this.$empty(this.password)) {
|
if (this.$empty(this.password)) {
|
||||||
this.errors.push({
|
this.errors.push({
|
||||||
name: "password",
|
name: 'password',
|
||||||
text: "Mật khẩu không được bỏ trống."
|
text: this.isVietnamese ? 'Mật khẩu không được bỏ trống.' : 'Password is required.',
|
||||||
});
|
});
|
||||||
} else if (this.password.length < 6) {
|
} else if (this.password.length < 6) {
|
||||||
this.errors.push({
|
this.errors.push({
|
||||||
name: "password",
|
name: 'password',
|
||||||
text: "Mật khẩu gồm 6 kí tự trở nên bao gồm chữ và số ."
|
text: this.isVietnamese
|
||||||
|
? 'Mật khẩu gồm 6 kí tự trở nên bao gồm chữ và số .'
|
||||||
|
: 'Password must be at least 6 characters long and include letters and numbers.',
|
||||||
});
|
});
|
||||||
} else if (
|
} else if (!(/\d/.test(this.password) && /[a-zA-Z]/.test(this.password))) {
|
||||||
!(/\d/.test(this.password) && /[a-zA-Z]/.test(this.password))
|
|
||||||
) {
|
|
||||||
this.errors.push({
|
this.errors.push({
|
||||||
name: "password",
|
name: 'password',
|
||||||
text: "Mật khẩu gồm 6 kí tự trở nên bao gồm chữ và số ."
|
text: this.isVietnamese
|
||||||
})
|
? 'Mật khẩu gồm 6 kí tự trở nên bao gồm chữ và số .'
|
||||||
|
: 'Password must be at least 6 characters long and include letters and numbers.',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return this.errors.length>0? true : false
|
return this.errors.length > 0 ? true : false;
|
||||||
},
|
},
|
||||||
async signin() {
|
async signin() {
|
||||||
if(this.checkError()) return
|
if (this.checkError()) return;
|
||||||
let conn = this.$findapi('login')
|
let conn = this.$findapi('login');
|
||||||
conn.params.filter = {username: this.username, password: this.password}
|
conn.params.filter = { username: this.username, password: this.password };
|
||||||
let result= await this.$getapi([conn])
|
let result = await this.$getapi([conn]);
|
||||||
if(result==='error') {
|
if (result === 'error') {
|
||||||
return this.$dialog('Đã xảy ra lỗi. Vui lòng thử lại hoặc liên hệ số hotline để được hỗ trợ.', 'Lỗi kết nối', 'Error', 10)
|
return this.$dialog(
|
||||||
|
`${
|
||||||
|
this.isVietnamese
|
||||||
|
? 'Đã xảy ra lỗi. Vui lòng thử lại hoặc liên hệ số hotline để được hỗ trợ.'
|
||||||
|
: 'An error occurred. Please try again or contact the hotline for support.'
|
||||||
|
}`,
|
||||||
|
`${this.isVietnamese ? 'Lỗi kết nối' : 'Connection error'}`,
|
||||||
|
'Error',
|
||||||
|
10,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let data = result.find(v => v.name==="login").data.rows
|
let data = result.find((v) => v.name === 'login').data.rows;
|
||||||
this.account = data
|
this.account = data;
|
||||||
this.fillData(data)
|
this.fillData(data);
|
||||||
},
|
},
|
||||||
invalidLogin(data) {
|
invalidLogin(data) {
|
||||||
if(!data) {
|
if (!data) {
|
||||||
const text = 'Tài khoản hoặc mật khẩu không chính xác'
|
const text = this.isVietnamese ? 'Tài khoản hoặc mật khẩu không chính xác' : 'Invalid username or password.';
|
||||||
this.errors.push({name: "username", text: text})
|
this.errors.push({ name: 'username', text: text });
|
||||||
this.errors.push({ name: "password", text: text})
|
this.errors.push({ name: 'password', text: text });
|
||||||
} else if(data.blocked) {
|
} else if (data.blocked) {
|
||||||
this.errors.push({name: "username", text: 'Tài khoản đang bị khóa. Đăng nhập không thành công'})
|
this.errors.push({
|
||||||
} else if(data.auth_status===1) {
|
name: 'username',
|
||||||
this.errors.push({name: "username", text: `Tài khoản đang chờ xác thực.`})
|
text: this.isVietnamese
|
||||||
|
? 'Tài khoản đang bị khóa. Đăng nhập không thành công'
|
||||||
|
: 'Your account has been blocked. Login failed.',
|
||||||
|
});
|
||||||
|
} else if (data.auth_status === 1) {
|
||||||
|
this.errors.push({
|
||||||
|
name: 'username',
|
||||||
|
text: this.isVietnamese ? `Tài khoản đang chờ xác thực.` : 'Your account is pending verification.',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return this.errors.length>0? true : false
|
return this.errors.length > 0 ? true : false;
|
||||||
},
|
},
|
||||||
async fillData(data) {
|
async fillData(data) {
|
||||||
if(this.invalidLogin(data)) return
|
if (this.invalidLogin(data)) return;
|
||||||
//check permision
|
//check permision
|
||||||
if(this.module!=='website') {
|
if (this.module !== 'website') {
|
||||||
let userapps = await this.$getdata('userapps', {user: data.id, apps__code: this.module}, undefined, true)
|
let userapps = await this.$getdata('userapps', { user: data.id, apps__code: this.module }, undefined, true);
|
||||||
if(!userapps) return this.$router.push('/welcome')
|
if (!userapps) return this.$router.push('/welcome');
|
||||||
}
|
}
|
||||||
this.login = data //store login
|
this.login = data; //store login
|
||||||
if(this.$store.state.link) {
|
if (this.$store.state.link) {
|
||||||
let ele = this.$copy(data)
|
let ele = this.$copy(data);
|
||||||
//get token & redirect link
|
//get token & redirect link
|
||||||
const browser = Bowser.getParser(window.navigator.userAgent);
|
const browser = Bowser.getParser(window.navigator.userAgent);
|
||||||
let obj = {browser: browser.getBrowserName(), browser_version: browser.getBrowserVersion(), platform: browser.getPlatform().type,
|
let obj = {
|
||||||
os: browser.getOSName(), user: data.id, token: this.$id()}
|
browser: browser.getBrowserName(),
|
||||||
ele.token = obj.token
|
browser_version: browser.getBrowserVersion(),
|
||||||
await this.$insertapi('authtoken', obj)
|
platform: browser.getPlatform().type,
|
||||||
let link = this.$store.state.link
|
os: browser.getOSName(),
|
||||||
if(data.type===3 && link.indexOf('y99')>=0) {
|
user: data.id,
|
||||||
link = link.indexOf('dev')>=0? 'https://dev.ctv.y99.vn' : 'https://ctv.y99.vn'
|
token: this.$id(),
|
||||||
|
};
|
||||||
|
ele.token = obj.token;
|
||||||
|
await this.$insertapi('authtoken', obj);
|
||||||
|
let link = this.$store.state.link;
|
||||||
|
if (data.type === 3 && link.indexOf('y99') >= 0) {
|
||||||
|
link = link.indexOf('dev') >= 0 ? 'https://dev.ctv.y99.vn' : 'https://ctv.y99.vn';
|
||||||
}
|
}
|
||||||
let href = `${link}?username=${ele.username}&token=${ele.token}&fullname=${ele.fullname}&userid=${ele.id}`
|
let href = `${link}?username=${ele.username}&token=${ele.token}&fullname=${ele.fullname}&userid=${ele.id}`;
|
||||||
if(ele.avatar) href = `${href}&avatar=${ele.avatar}`
|
if (ele.avatar) href = `${href}&avatar=${ele.avatar}`;
|
||||||
window.location.href = href
|
window.location.href = href;
|
||||||
} else this.redirectUrl()
|
} else this.redirectUrl();
|
||||||
},
|
},
|
||||||
async sendNoti(obj) {
|
async sendNoti(obj) {
|
||||||
let found = this.$findapi('notiform')
|
let found = this.$findapi('notiform');
|
||||||
found.params.filter = {code: 'login-alert'}
|
found.params.filter = { code: 'login-alert' };
|
||||||
const result = await this.$getapi([found])
|
const result = await this.$getapi([found]);
|
||||||
let data = result[0].data.rows[0]
|
let data = result[0].data.rows[0];
|
||||||
let content = data.detail
|
let content = data.detail;
|
||||||
content = content.replace('[1]', this.username)
|
content = content.replace('[1]', this.username);
|
||||||
content = content.replace('[2]', obj.browser)
|
content = content.replace('[2]', obj.browser);
|
||||||
content = content.replace('[3]', obj.browser_version)
|
content = content.replace('[3]', obj.browser_version);
|
||||||
content = content.replace('[4]', obj.platform)
|
content = content.replace('[4]', obj.platform);
|
||||||
content = content.replace('[5]', obj.os)
|
content = content.replace('[5]', obj.os);
|
||||||
content = content.replace('[6]', this.$dayjs().format("DD/MM/YYYY HH:mm"))
|
content = content.replace('[6]', this.$dayjs().format('DD/MM/YYYY HH:mm'));
|
||||||
let ele = {title: data.name, content: content, user: [obj.user.toString()], type: 1}
|
let ele = { title: data.name, content: content, user: [obj.user.toString()], type: 1 };
|
||||||
await this.$insertapi('notification', ele)
|
await this.$insertapi('notification', ele);
|
||||||
},
|
},
|
||||||
accountRecovery() {
|
accountRecovery() {
|
||||||
this.$router.push({path: '/account/recovery'})
|
this.$router.push({ path: '/account/recovery' });
|
||||||
},
|
},
|
||||||
async redirectUrl() {
|
async redirectUrl() {
|
||||||
this.$router.push(this.$route.query.href || '/welcome')
|
this.$router.push(this.$route.query.href || '/welcome');
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.wrapper-login {
|
||||||
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
</script>
|
|
||||||
|
.wrapper-login .login-box {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -6,11 +6,20 @@
|
|||||||
<div class="hero-body px-2 py-5">
|
<div class="hero-body px-2 py-5">
|
||||||
<article class="message is-primary">
|
<article class="message is-primary">
|
||||||
<div class="message-body has-text-black fs-18 py-3 mt-0">
|
<div class="message-body has-text-black fs-18 py-3 mt-0">
|
||||||
No access permission.
|
{{ isVietnamese ? 'Không có quyền truy cập.' : 'No access permission.' }}
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
isVietnamese() {
|
||||||
|
return navigator.language.toLowerCase().startsWith('vi');
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user