feat:登录
Showing
24 changed files
with
0 additions
and
484 deletions
| ... | @@ -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', | ... | ... |
src/views/login/auth-redirect.vue
deleted
100644 → 0
| 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 |
13.1 KB
729 KB
src/views/login/img/bazaaz.png
deleted
100644 → 0
2.58 MB
src/views/login/img/code.png
deleted
100644 → 0
8.19 KB
src/views/login/img/erweima.png
deleted
100644 → 0
65.2 KB
src/views/login/img/jiancelogo.png
deleted
100644 → 0
76.9 KB
src/views/login/img/jiarr.png
deleted
100644 → 0
2.68 KB
src/views/login/img/jieshao.png
deleted
100644 → 0
2.48 KB
src/views/login/img/login-title.png
deleted
100644 → 0
65.8 KB
11.6 KB
src/views/login/img/qiye.png
deleted
100644 → 0
4.13 KB
src/views/login/img/shichang.png
deleted
100644 → 0
4.46 KB
src/views/login/img/shichanglogo.png
deleted
100644 → 0
65.7 KB
src/views/login/img/xieyi.png
deleted
100644 → 0
2.53 KB
src/views/login/img/xinBg.png
deleted
100644 → 0
1.34 MB
src/views/login/img/xinlogo.png
deleted
100644 → 0
56.4 KB
src/views/login/img/yonghu.png
deleted
100644 → 0
4.84 KB
src/views/login/img/zhengfu.png
deleted
100644 → 0
4.27 KB
src/views/login/img/zhinan.png
deleted
100644 → 0
2.91 KB
src/views/login/login.vue
deleted
100644 → 0
| 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 |
-
Please register or sign in to post a comment