f745e1dd by 任超

feat:登录

1 parent 81f92c0a
...@@ -17,7 +17,6 @@ import router from './router' ...@@ -17,7 +17,6 @@ import router from './router'
17 import _ from 'lodash' 17 import _ from 'lodash'
18 18
19 import './icons' // icon 19 import './icons' // icon
20 import './permission' // permission control
21 import * as filters from './filters' // global filters 20 import * as filters from './filters' // global filters
22 Vue.use(lbTable); 21 Vue.use(lbTable);
23 22
......
...@@ -21,16 +21,6 @@ export const constantRoutes = [ ...@@ -21,16 +21,6 @@ export const constantRoutes = [
21 ] 21 ]
22 }, 22 },
23 { 23 {
24 path: '/login',
25 component: () => import('@/views/login/login'),
26 hidden: true
27 },
28 {
29 path: '/auth-redirect',
30 component: () => import('@/views/login/auth-redirect'),
31 hidden: true
32 },
33 {
34 path: '/', 24 path: '/',
35 component: Layout, 25 component: Layout,
36 redirect: '/home', 26 redirect: '/home',
......
1 <script>
2 export default {
3 name: 'AuthRedirect',
4 created() {
5 const hash = window.location.search.slice(1)
6 if (window.localStorage) {
7 window.localStorage.setItem('x-admin-oauth-code', hash)
8 window.close()
9 }
10 },
11 render: function(h) {
12 return h() // avoid warning message
13 }
14 }
15 </script>
1 <template>
2 <div class="jc-component__range">
3 <div v-loading="loading" class="jc-range" :class="rangeStatus ? 'success' : ''">
4 <i @mousedown="rangeMove" :class="rangeStatus ? successIcon : startIcon"></i>
5 {{ rangeStatus ? successText : startText }}
6 </div>
7 </div>
8 </template>
9
10 <script>
11 import * as login from '@/api/login'
12 export default {
13 props: {
14 // 成功之后的函数
15 successFun: {
16 type: Function,
17 },
18 //成功图标
19 successIcon: {
20 type: String,
21 default: 'el-icon-check',
22 },
23 //成功文字
24 successText: {
25 type: String,
26 default: '验证成功',
27 },
28 //开始的图标
29 startIcon: {
30 type: String,
31 default: 'el-icon-right',
32 },
33 //开始的文字
34 startText: {
35 type: String,
36 default: '请按住滑块,拖动到最右边',
37 },
38 //失败之后的函数
39 errorFun: {
40 type: Function,
41 },
42 //或者用值来进行监听
43 status: {
44 type: String,
45 },
46 },
47 data () {
48 return {
49 loading: false,
50 disX: 0,
51 rangeStatus: false,
52 str: {},
53 }
54 },
55 methods: {
56 moveFn (e) {
57 let ele = e.target
58 ele.style.transition = '.5s all'
59 ele.style.transform = 'translateX(0)'
60 this.rangeStatus = false
61 // 执行成功的函数
62 this.errorFun()
63 },
64 //滑块移动
65 rangeMove (e) {
66 this.str = e
67 let ele = e.target
68 let startX = e.clientX
69 let eleWidth = ele.offsetWidth
70 let parentWidth = ele.parentElement.offsetWidth
71 let MaxX = parentWidth - eleWidth
72
73 if (this.rangeStatus) {
74 //不运行
75 return false
76 }
77 document.onmousemove = (e) => {
78 let endX = e.clientX
79 this.disX = endX - startX
80 if (this.disX <= 0) {
81 this.disX = 0
82 }
83 if (this.disX >= MaxX - eleWidth) {
84 //减去滑块的宽度,体验效果更好
85 this.disX = MaxX
86 }
87 ele.style.transition = '.1s all'
88 ele.style.background = 'red!important'
89 ele.style.transform = 'translateX(' + this.disX + 'px)'
90 e.preventDefault()
91 }
92
93 document.onmouseup = async () => {
94
95 if (this.disX !== MaxX) {
96 ele.style.transition = '.5s all'
97 ele.style.transform = 'translateX(0)'
98 // 执行成功的函数
99 this.errorFun && this.errorFun()
100 }
101 else {
102 this.successFun && this.successFun()
103 this.rangeStatus = true
104 this.loading = true
105 if (this.status) {
106 this.$parent[this.status] = true
107 }
108 }
109 document.onmousemove = null
110 document.onmouseup = null
111 }
112 },
113 },
114 }
115 </script>
116
117 <style lang="scss" scoped>
118 @mixin jc-flex {
119 display: flex;
120 justify-content: center;
121 align-items: center;
122 }
123
124 .jc-component__range {
125 .jc-range {
126 background-color: #F7FAFE;
127 border: 1px solid #D8E0E9;
128 position: relative;
129 transition: 1s all;
130 user-select: none;
131 color: #9B9B9B;
132 display: flex;
133 // justify-content: center;
134 padding-left: 50px;
135 align-items: center;
136 height: 40px;
137
138 /*no*/
139 &.success {
140 background-color: #D2F5EF;
141 color: #4caf50;
142 border: 1px solid #99D5D0;
143 font-size: 16px;
144 justify-content: center;
145 padding-left: 0px;
146
147 i {
148 color: #ffffff;
149 background-color: #51CCBF;
150 }
151 }
152
153 i {
154 position: absolute;
155 left: 0;
156 width: 38px;
157 /*no*/
158 height: 40px;
159
160 background-color: #fff;
161 border: 1px solid #d8d8d8;
162 cursor: pointer;
163 font-size: 14px;
164 color: #829ABA;
165 @include jc-flex;
166 }
167 }
168 }
169 </style>
170 <style lang="scss" scoped>
171 /deep/.el-loading-spinner {
172 top: 62%;
173
174 .circular {
175 height: 35px !important;
176 width: 30px !important;
177 }
178 }
179
180 /deep/.el-loading-mask {
181 background-color: rgba(255, 255, 255, 1);
182 }
183 </style>
...\ No newline at end of file ...\ No newline at end of file
1 <template>
2 <div class="login">
3 <div class="login-header-title">
4 <img src="./img/login-title.png">
5 </div>
6 <div class="login-content_code">
7 <div class="hidden-bos">
8 <img src='./img/72054ab975174650a84d0a975de6712.png' @click.stop="Codeclick('2')" alt="">
9 </div>
10 <div class="login-form">
11 <h3 class="login-title ">
12 <p>{{ activeName }}</p>
13 </h3>
14 <el-form :model="ruleForm" :rules="rules" size="large" ref="ruleForm">
15 <el-form-item prop="username">
16 <el-input type="text" placeholder="请输入账号/手机号" v-model="ruleForm.username">
17 <svg-icon slot="prefix" icon-class="username" />
18 </el-input>
19 </el-form-item>
20 <el-form-item prop="password">
21 <el-input type="password" placeholder="请输入登录密码" v-model="ruleForm.password">
22 <svg-icon slot="prefix" icon-class="password" />
23 </el-input>
24 </el-form-item>
25 <el-form-item prop="code">
26 <JcRange ref='jcrangeRef' :successFun="verificate_sucess" :errorFun="verificate_error"></JcRange>
27 </el-form-item>
28 <el-form-item class="login-button-form">
29 <el-button type="primary" class="submit-button" @click="submitForm('ruleForm')">登录
30 </el-button>
31 </el-form-item>
32 </el-form>
33 </div>
34 </div>
35 <div class="login-footer">
36 Copyright © 2021-2025闽ICP备20013799号-2
37 </div>
38 </div>
39 </template>
40 <script>
41 import * as login from '@/api/login'
42 import JcRange from './components/JcRange'
43 import dialogBox from '@/components/dialogBox/index';
44 export default {
45 components: {
46 JcRange,
47 dialogBox
48 },
49 data () {
50 return {
51 activeName: '登录',
52 ruleForm: {
53 username: '',
54 password: '',
55 location: '',
56 code: ''
57 },
58 rules: {
59 username: [
60 { required: true, message: '请输入账号/手机号', trigger: 'blur' },
61 ],
62 password: [
63 {
64 required: true,
65 message: '请输入登录密码',
66 trigger: 'blur'
67 }
68 ],
69 code: [
70 {
71 required: true,
72 message: '请滑动完成验证',
73 trigger: 'blur'
74 }
75 ]
76 },
77 loading: false,
78 redirect: undefined,
79 otherQuery: {}
80 }
81 },
82 watch: {
83 $route: {
84 handler: function (route) {
85 const query = route.query
86 if (query) {
87 this.redirect = query.redirect
88 this.otherQuery = this.getOtherQuery(query)
89 }
90 },
91 immediate: true
92 },
93
94 },
95 methods: {
96 async getcode () {
97 try {
98 const res = await login.verifyCode()
99 this.ruleForm.code = res
100 if (this.ruleForm.code !== '') {
101 this.$refs.jcrangeRef.loading = false
102 }
103 } catch (error) {
104 this.$refs.jcrangeRef.loading = true
105 this.$message.error('获取验证码失败')
106 }
107 },
108 handleCode () {
109 this.getcode()
110 },
111 submitForm (formName) {
112 this.$refs[formName].validate(async valid => {
113 if (valid) {
114 this.$store.dispatch('user/login', this.ruleForm).then((res) => {
115 this.$router.push({
116 path: this.redirect || '/',
117 query: this.otherQuery
118 })
119 }).catch(e => {
120 this.$refs.jcrangeRef.disX = 0
121 this.$refs.jcrangeRef.moveFn(this.$refs.jcrangeRef.str)
122 })
123 } else {
124 return false
125 }
126 })
127 },
128 getOtherQuery (query) {
129 return Object.keys(query).reduce((acc, cur) => {
130 if (cur !== 'redirect') {
131 acc[cur] = query[cur]
132 }
133 return acc
134 }, {})
135 },
136
137 // 验证码
138 verificate_sucess () {
139 this.getcode()
140 },
141 verificate_error () {
142 this.ruleForm.code = ''
143 }
144 }
145 }
146 </script>
147 <style lang="scss" scoped>
148 .login {
149 width: 100%;
150 height: 100%;
151 background: url("./img/xinBg.png") no-repeat;
152 background-size: 100% auto;
153 display: flex;
154 align-items: center;
155 flex-direction: column;
156 position: relative;
157
158 .login-header-title {
159 width: 40%;
160 margin: 5% 0 40px 0;
161 min-height: 65px;
162
163 img {
164 width: 100%;
165 }
166 }
167
168 .login-content_code {
169 width: 25%;
170 background-color: #ffffff;
171 box-shadow: 0px 0px 30px 0px rgba(130, 154, 186, 0.2);
172 border-radius: 8px;
173 background-repeat: no-repeat;
174 background-position: top right;
175 position: relative;
176
177 .hidden-box {
178 text-align: right;
179 cursor: pointer;
180 position: absolute;
181 right: 0;
182 top: 0;
183
184 img {
185 width: 45%;
186 }
187 }
188
189 .hidden-bos {
190 text-align: right;
191 cursor: pointer;
192 position: absolute;
193 right: 0;
194 top: 0;
195
196 img {
197 width: 45%;
198 }
199 }
200
201 .login-form {
202 width: 100%;
203 min-height: 385px;
204 padding: 20px 30px 0 30px;
205 box-sizing: border-box;
206
207 .code-item {
208 display: flex;
209 align-items: center;
210 height: 40px;
211 width: 100%;
212
213 img {
214 width: 100px;
215 height: 40px;
216 float: right;
217 cursor: pointer;
218 }
219 }
220
221 /deep/.el-input__prefix {
222 display: flex;
223 align-items: center;
224 justify-content: center;
225 margin-left: 10px;
226 }
227
228 /deep/.el-input__prefix:after {
229 content: "";
230 position: absolute;
231 right: -9px;
232 top: 13px;
233 height: 14px;
234 border-right: 1px solid #d9d9d9;
235 }
236
237 /deep/.el-input__inner {
238 padding-left: 50px;
239 }
240
241 .code-input {
242 position: relative;
243
244 /deep/.el-input__inner {
245 border-right: none;
246 }
247
248 .verification-code {
249 width: 96px;
250 height: 31px;
251 }
252
253 /deep/.el-input-group__append {
254 border-left: none;
255 background: none;
256 }
257 }
258
259 .login-title {
260 margin-bottom: 20px;
261 text-align: center;
262
263 p {
264 font-size: 20px;
265 color: #8a8a8a;
266 width: 25%;
267 margin: 0 auto;
268 border-bottom: 2px solid #0f93f6;
269 padding-bottom: 10px;
270 }
271 }
272 }
273 }
274 }
275 </style>
...\ No newline at end of file ...\ No newline at end of file