|
@@ -0,0 +1,382 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="login-container" id="particles-js">
|
|
|
|
|
+ <div class="bg-logo"></div>
|
|
|
|
|
+ <el-form
|
|
|
|
|
+ ref="loginForm"
|
|
|
|
|
+ :model="loginForm"
|
|
|
|
|
+ :rules="loginRules"
|
|
|
|
|
+ class="login-form"
|
|
|
|
|
+ autocomplete="on"
|
|
|
|
|
+ label-position="left">
|
|
|
|
|
+
|
|
|
|
|
+ <div class="title-container">
|
|
|
|
|
+ <!-- <h3 class="title">{{appName}}</h3> -->
|
|
|
|
|
+ <img class="csms-logo" src="../../icons/logo.png"/>
|
|
|
|
|
+ <p class="title">CSMS LOGIN</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <el-form-item prop="username">
|
|
|
|
|
+ <div class="form-login-input">
|
|
|
|
|
+ <span class="svg-container">
|
|
|
|
|
+ <svg-icon icon-class="user" />
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ ref="username"
|
|
|
|
|
+ v-model="loginForm.username"
|
|
|
|
|
+ name="username"
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ tabindex="1"
|
|
|
|
|
+ autocomplete="on"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ maxlength="50"
|
|
|
|
|
+ @focus="() => focusFiled.username = true"
|
|
|
|
|
+ @blur="() => focusFiled.username = false"/>
|
|
|
|
|
+ <label :class='isNameValid ? "focus" : ""'>Username</label>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item prop="password">
|
|
|
|
|
+ <div class="form-login-input">
|
|
|
|
|
+ <span class="svg-container">
|
|
|
|
|
+ <svg-icon icon-class="password" />
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ ref="password"
|
|
|
|
|
+ v-model="loginForm.password"
|
|
|
|
|
+ :type="passwordType"
|
|
|
|
|
+ name="password"
|
|
|
|
|
+ tabindex="2"
|
|
|
|
|
+ autocomplete="on"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ maxlength="20"
|
|
|
|
|
+ @keyup.enter.native="handleLogin"
|
|
|
|
|
+ @focus="() => focusFiled.password = true"
|
|
|
|
|
+ @blur="() => focusFiled.password = false"
|
|
|
|
|
+ />
|
|
|
|
|
+ <span class="show-pwd" @click="showPwd">
|
|
|
|
|
+ <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <label :class='isPsdValid ? "focus" : ""'>Password</label>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ :loading="loading"
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ class="login-button"
|
|
|
|
|
+ @click.native.prevent="handleLogin">
|
|
|
|
|
+ Login
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ <div class="copyinfo">©{{copyYear}} {{company}}</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script>
|
|
|
|
|
+import { validUsername } from '@/utils/validate'
|
|
|
|
|
+import VueRouter from 'vue-router'
|
|
|
|
|
+import { Message } from 'element-ui'
|
|
|
|
|
+import settings from '../../settings.js'
|
|
|
|
|
+import {getUserName} from '../../utils/auth.js'
|
|
|
|
|
+import particles from 'particles.js'
|
|
|
|
|
+import animateJson from './animate.json'
|
|
|
|
|
+const { isNavigationFailure, NavigationFailureType } = VueRouter
|
|
|
|
|
+
|
|
|
|
|
+export default {
|
|
|
|
|
+ name: 'Login',
|
|
|
|
|
+ data() {
|
|
|
|
|
+ const validatePassword = (rule, value, callback) => {
|
|
|
|
|
+ if (value.length < 6) {
|
|
|
|
|
+ callback(new Error('The password can not be less than 6 digits'))
|
|
|
|
|
+ } else {
|
|
|
|
|
+ callback()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return {
|
|
|
|
|
+ year: 2023,
|
|
|
|
|
+ appName: settings.title,
|
|
|
|
|
+ company: settings.company,
|
|
|
|
|
+ loginForm: {
|
|
|
|
|
+ username: '',
|
|
|
|
|
+ password: ''
|
|
|
|
|
+ },
|
|
|
|
|
+ loginRules: {
|
|
|
|
|
+ username: [{
|
|
|
|
|
+ required: true,
|
|
|
|
|
+ trigger: 'blur',
|
|
|
|
|
+ message: "Please type username"
|
|
|
|
|
+ }],
|
|
|
|
|
+ password: [{
|
|
|
|
|
+ required: true,
|
|
|
|
|
+ trigger: 'blur',
|
|
|
|
|
+ message: "Please type password"
|
|
|
|
|
+ //validator: validatePassword
|
|
|
|
|
+ }]
|
|
|
|
|
+ },
|
|
|
|
|
+ passwordType: 'password',
|
|
|
|
|
+ loading: false,
|
|
|
|
|
+ redirect: undefined,
|
|
|
|
|
+ otherQuery: {},
|
|
|
|
|
+ focusFiled: {
|
|
|
|
|
+ username: false,
|
|
|
|
|
+ password: false
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ watch: {
|
|
|
|
|
+ $route: {
|
|
|
|
|
+ handler: function(route) {
|
|
|
|
|
+ const query = route.query
|
|
|
|
|
+ if (query) {
|
|
|
|
|
+ this.redirect = query.redirect
|
|
|
|
|
+ this.otherQuery = this.getOtherQuery(query)
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ immediate: true
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ computed: {
|
|
|
|
|
+ copyYear() {
|
|
|
|
|
+ const year = new Date().getFullYear();
|
|
|
|
|
+ if (year > this.year) {
|
|
|
|
|
+ return this.year + "-" + year;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return this.year;
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ isNameValid() {
|
|
|
|
|
+ return (this.loginForm.username !== "" || this.focusFiled.username)
|
|
|
|
|
+ },
|
|
|
|
|
+ isPsdValid() {
|
|
|
|
|
+ return (this.loginForm.password !== "" || this.focusFiled.password)
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ created() {
|
|
|
|
|
+ // window.addEventListener('storage', this.afterQRScan)
|
|
|
|
|
+ const user = getUserName()
|
|
|
|
|
+ if (user) {
|
|
|
|
|
+ this.loginForm.username = user;
|
|
|
|
|
+ }
|
|
|
|
|
+ console.log(animateJson);
|
|
|
|
|
+ //
|
|
|
|
|
+ },
|
|
|
|
|
+ beforeMount() {
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ const sss = document.getElementById("particles-js");
|
|
|
|
|
+ console.log(sss);
|
|
|
|
|
+ particlesJS('particles-js', animateJson);
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ mounted() {
|
|
|
|
|
+ if (this.loginForm.username === '') {
|
|
|
|
|
+ this.$refs.username.focus()
|
|
|
|
|
+ } else if (this.loginForm.password === '') {
|
|
|
|
|
+ this.$refs.password.focus()
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ destroyed() {
|
|
|
|
|
+ // window.removeEventListener('storage', this.afterQRScan)
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ showPwd() {
|
|
|
|
|
+ if (this.passwordType === 'password') {
|
|
|
|
|
+ this.passwordType = ''
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.passwordType = 'password'
|
|
|
|
|
+ }
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ this.$refs.password.focus()
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ handleLogin() {
|
|
|
|
|
+ this.$refs.loginForm.validate(valid => {
|
|
|
|
|
+ if (valid) {
|
|
|
|
|
+ this.loading = true
|
|
|
|
|
+ this.$store.dispatch('user/login', this.loginForm).then((response) => {
|
|
|
|
|
+ let path = this.redirect || '/'
|
|
|
|
|
+ if (response.data.roleName === "MCST") {
|
|
|
|
|
+ path = '/site-management'
|
|
|
|
|
+ } else if (response.data.resources.length > 0) {
|
|
|
|
|
+ let validPath = false;
|
|
|
|
|
+ for (let _route of response.data.resources) {
|
|
|
|
|
+ if (path.indexOf(_route.resourcePath) >= 0) {
|
|
|
|
|
+ validPath = true;
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!validPath) {
|
|
|
|
|
+ path = response.data.resources[0].resourcePath;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ this.$router.push({
|
|
|
|
|
+ path: path,
|
|
|
|
|
+ query: this.otherQuery,
|
|
|
|
|
+ }).catch((failure) => {
|
|
|
|
|
+ if (!isNavigationFailure(failure, NavigationFailureType.redirected)) {
|
|
|
|
|
+ throw failure
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ this.loading = false
|
|
|
|
|
+ }).catch((error) => {
|
|
|
|
|
+ Message.error(error.message)
|
|
|
|
|
+ this.loading = false
|
|
|
|
|
+ });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ console.log('error submit!!')
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ getOtherQuery(query) {
|
|
|
|
|
+ return Object.keys(query).reduce((acc, cur) => {
|
|
|
|
|
+ if (cur !== 'redirect') {
|
|
|
|
|
+ acc[cur] = query[cur]
|
|
|
|
|
+ }
|
|
|
|
|
+ return acc
|
|
|
|
|
+ }, {})
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
|
+/* reset element-ui css */
|
|
|
|
|
+.login-container {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ min-height: 100%;
|
|
|
|
|
+ user-select: none;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ background: linear-gradient(0deg, #333333 0%, #A1A1A1 100%);
|
|
|
|
|
+
|
|
|
|
|
+ .login-form {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ z-index: 2;
|
|
|
|
|
+ margin: 0 auto;
|
|
|
|
|
+ max-width: 420px;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ border-radius: 3px;
|
|
|
|
|
+ padding: 30px 40px 50px;
|
|
|
|
|
+ box-shadow: 1px 1px 5px 3px rgba(0,0,0,.2);
|
|
|
|
|
+ }
|
|
|
|
|
+ .title-container {
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ padding: 20px 0 0;
|
|
|
|
|
+
|
|
|
|
|
+ .title {
|
|
|
|
|
+ font-size: 18px;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ margin: 20px 0;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ }
|
|
|
|
|
+ .csms-logo {
|
|
|
|
|
+ max-width: 200px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .form-login-input {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ padding: 0 10px;
|
|
|
|
|
+ margin-top: 20px;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ border-bottom: 1px solid #999;
|
|
|
|
|
+ label {
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ color: #aaa;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ position:absolute;
|
|
|
|
|
+ padding-top: 7px;
|
|
|
|
|
+ padding-left: 45px;
|
|
|
|
|
+ font-weight: normal;
|
|
|
|
|
+ pointer-events: none;
|
|
|
|
|
+ transition: all 0.3s;
|
|
|
|
|
+ }
|
|
|
|
|
+ label.focus {
|
|
|
|
|
+ top: -30px;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ font-size: 15px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ padding-left: 5px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .svg-container {
|
|
|
|
|
+ width: 30px;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ padding: 6px 6px 6px 5px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .el-input {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ height: 42px;
|
|
|
|
|
+
|
|
|
|
|
+ &::v-deep input {
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ height: 42px;
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ padding: 0 5px;
|
|
|
|
|
+ border-radius: 0px;
|
|
|
|
|
+ -webkit-appearance: none;
|
|
|
|
|
+ background: transparent;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .show-pwd {
|
|
|
|
|
+ color: #999;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ user-select: none;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .login-button {
|
|
|
|
|
+ width:100%;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ padding: 15px;
|
|
|
|
|
+ margin-top: 40px;
|
|
|
|
|
+ margin-bottom: 30px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .copyinfo {
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ bottom: 10px;
|
|
|
|
|
+ color: #e0e0e0;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ user-select: none;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ transform: scale(.8);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .bg-logo {
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ z-index: 1;
|
|
|
|
|
+ opacity: .3;
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ filter: blur(30px);
|
|
|
|
|
+ pointer-events: none;
|
|
|
|
|
+ background-size: contain;
|
|
|
|
|
+ background-position: center;
|
|
|
|
|
+ background-repeat: no-repeat;
|
|
|
|
|
+ background-image: url(../../assets/logo.png);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|
|
|
|
|
+<style>
|
|
|
|
|
+ .particles-js-canvas-el {
|
|
|
|
|
+ z-index: 1;
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ }
|
|
|
|
|
+</style>
|