long
2024-02-04 ae5ea1a3d06324d85f4b04f17bac0dc5572a5a8f
提交 | 用户 | age
aeb317 1 <template>
J 2   <div class="login-container flex flex-ver">
3     <div class="login-form">
4       <!-- <div class="title-container flex flex-ver mb20">
5         <img class="login_logo" src="../../assets/login/logo.png">
6         <h3 class="title">芙艾预约管理系统</h3>
7         <div class="title ml10">芙艾(P-HIS)医院管理系统</div>
8         <h3 class="title ml10">昊芝综合医疗运营管理系统</h3>
9       </div> -->
10       <!-- 账号登录 -->
11       <div v-if="loginType===0">
12         <el-form ref="loginForm" :model="loginForm" :rules="loginRules" autocomplete="on" label-position="left">
13
14           <el-form-item prop="username">
15             <span class="svg-container">
16               <svg-icon icon-class="user" />
17             </span>
18             <el-input
19               ref="username"
20               v-model="loginForm.username"
21               placeholder="请输入账号"
22               name="username"
23               type="text"
24               tabindex="1"
25               autocomplete="on"
26               @keyup.enter.native="handleLogin"
27             />
28           </el-form-item>
29
30           <el-tooltip v-model="capsTooltip" content="Caps lock is On" placement="right" manual>
31             <el-form-item prop="password">
32               <span class="svg-container">
33                 <svg-icon icon-class="password" />
34               </span>
35               <el-input
36                 :key="passwordType"
37                 ref="password"
38                 v-model="loginForm.password"
39                 :type="passwordType"
40                 placeholder="请输入密码"
41                 name="password"
42                 tabindex="2"
43                 autocomplete="on"
44                 @keyup.native="checkCapslock"
45                 @blur="capsTooltip = false"
46                 @keyup.enter.native="handleLogin"
47               />
48               <span class="show-pwd" @click="showPwd">
49                 <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
50               </span>
51             </el-form-item>
52           </el-tooltip>
53
54           <div class="flex flex-start flex-sb">
55             <el-form-item prop="safecode" class="flex-1">
56               <span class="svg-container">
57                 <svg-icon icon-class="safecode" />
58               </span>
59               <el-input
60                 ref="safecode"
61                 v-model="loginForm.safecode"
62                 style="width: 70%"
63                 placeholder="请输入验证码"
64                 name="safecode"
65                 type="text"
66                 tabindex="3"
67                 autocomplete="off"
68                 @keyup.enter.native="handleLogin"
69               />
70               <el-image
71                 v-if="isTestView"
72                 class="safecode-img"
73                 :src="safecodeImg"
74                 fit="fill"
75                 @click="getSafeCodeImg"
76               >
77                 <div slot="error" class="image-slot">
78                   <i class="el-icon-picture-outline" />
79                 </div>
80               </el-image>
81             </el-form-item>
82             <el-button v-if="!isTestView" class="ml10 mt5" :disabled="isShowCount" type="blackblue" @click="sendCode">
83               {{ isShowCount ? secondCount + '秒后重发' : '发送验证码' }}
84             </el-button>
85           </div>
86
87           <!-- <el-form-item prop="safecode">
88             <span class="svg-container">
89               <svg-icon icon-class="safecode" />
90             </span>
91             <el-input
92               ref="safecode"
93               v-model="loginForm.safecode"
94               style="width: 60%"
95               placeholder="请输入验证码"
96               name="safecode"
97               type="text"
98               tabindex="3"
99               autocomplete="off"
100               @keyup.enter.native="handleLogin"
101             />
102             <el-image
103               class="safecode-img"
104               :src="safecodeImg"
105               fit="fill"
106               @click="getSafeCodeImg"
107             >
108               <div slot="error" class="image-slot">
109                 <i class="el-icon-picture-outline" />
110               </div>
111             </el-image>
112           </el-form-item> -->
113
114         </el-form>
115
116         <div>
117           <el-button :loading="loading" type="blackblue" style="width:100%;margin-bottom:20px;border-radius: 22px;" @click.native.prevent="handleLogin">登录</el-button>
118         </div>
119         <div>
120           <el-button v-if="!isTestView" :loading="loading" plain style="width:100%;border-radius: 22px;" @click="loginType=1">切换扫码登录</el-button>
121           <!-- <el-button v-else :loading="loading" plain style="width:100%;border-radius: 22px;" @click="simulateLogin">模拟扫码登录</el-button> -->
122         </div>
123         <!-- 企业微信直接带上state和code,无需再用按钮 -->
124         <!-- <div>
125           <el-button :loading="loading" plain style="width:100%;margin-top:20px;border-radius: 22px;" @click.native.prevent="handleWebLogin">网页登录</el-button>
126         </div> -->
127       </div>
128       <!-- 扫码登录 -->
129       <div v-if="loginType===1">
130         <!-- 扫码 -->
131         <div v-if="!show_role_list" id="wx_reg" class="flex flex-align-center" />
132         <!-- 扫码回调后 -->
133         <div v-if="show_role_list">
134           <div class="role-list-title">请选择角色</div>
135           <div class="role-list flex flex-wrap" :class="{'block-list': roleList.length<=4}">
136             <!-- 20231117 long 加个双击进入 -->
137             <div v-for="(item,index) in roleList" :key="index" class="item flex flex-ver" :class="{active:item.id == roleId}" @click="selectRole(item.id)" @dblclick="item.id == roleId?selectCodeLoginTest(roleId):noop()">
138               <div class="flex-1">
139                 <div class="role-name ell">{{ item.roleName }}</div>
140                 <div class="shop-name ell">{{ item.shopName }}</div>
141               </div>
142               <i class="el-icon-check" />
143             </div>
144           </div>
145           <div>
146             <el-button v-if="isTestView" :loading="loading" :disabled="!roleId" type="blackblue" style="width: 100%;margin-bottom:20px;border-radius: 22px;" @click.native.prevent="selectCodeLoginTest(roleId)">{{ roleId ? '马上登录' : '选择角色后登录' }}</el-button>
147             <el-button v-else :loading="loading" :disabled="!roleId" type="blackblue" style="width: 100%;margin-bottom:20px;border-radius: 22px;" @click.native.prevent="selectCodeLogin(roleId)">{{ roleId ? '马上登录' : '选择角色后登录' }}</el-button>
148           </div>
149           <div v-if="!isTestView">
150             <el-button type="blackblue" style="width: 100%;margin-bottom:20px;border-radius: 22px;" @click.native.prevent="scanAgain">重新扫码<i class="el-icon-refresh-right el-icon--right" /></el-button>
151           </div>
152         </div>
153         <!-- <el-button :loading="loading" plain style="width:100%;border-radius: 22px;" @click="loginType=0">切换账号登录<i class="el-icon-arrow-right el-icon--right" /></el-button> -->
154         <!-- <el-button :loading="loading" plain style="width:100%;border-radius: 22px;" @click="loginType=0">切换登录方式<i class="el-icon-arrow-right el-icon--right" /></el-button> -->
155       </div>
156
157     </div>
158   </div>
159 </template>
160
161 <script>
162 // 设置token和用户数据
163 import { setToken, setUserData } from '@/utils/auth' // get token from session
164 // 基础配置 - 获取当前环境
165 const baseConfig = require('../../config/index')
166 // 登录接口的 mockData
167 const g_mockData = require('./g_mockData.js')
168 // 获取参数方法
169 import { getQueryObj } from '@/pages/login/getQueryObj'
170 import Req from '../../utils/jun_httpInstall' // http 请求
171 export default {
172   name: 'Login',
173   components: {},
174   data() {
175     const validateUsername = (rule, value, callback) => {
176       if (!value) {
177         callback(new Error('请输入账号'))
178       } else {
179         callback()
180       }
181     }
182     const validatePassword = (rule, value, callback) => {
183       if (value ? value.length < 6 : !value) {
184         callback(new Error('密码不能少于6位'))
185       } else {
186         callback()
187       }
188     }
189     const validateSafecode = (rule, value, callback) => {
190       if (!value) {
191         callback(new Error('请输入验证码'))
192       } else {
193         callback()
194       }
195     }
196     return {
197       // 当前登陆环境
198       localOnline: baseConfig.localOnline, // 本地连线上(和isTestView一起判断) 20230619 long
199
200       loginForm: {
201         username: '',
202         password: '',
203         safecode: '',
204         checkedId: ''
205       },
206       loginRules: {
207         username: [{ required: true, trigger: 'blur', validator: validateUsername }],
208         password: [{ required: true, trigger: 'blur', validator: validatePassword }],
209         safecode: [{ required: true, trigger: 'blur', validator: validateSafecode }]
210       },
211       passwordType: 'password',
212       capsTooltip: false,
213       loading: false,
214       showDialog: false,
215       redirect: undefined,
216       otherQuery: {},
217       // 测试服用图片验证码  线上用发送手机验证码
218       safecodeImg: '',
219       secondCount: 0, // 秒
220       telCode: '', // 短信验证码
221       messageId: '', // 发送成功
222       isShowCount: false,
223       timer: null,
224
225       loginType: 0,
226
227       // 20230216 long 用户重定向页面识别登录类型
228       // 扫码登录STATE_SCAN、网页登录TATE_WEB
229       state: '',
230       STATE_SCAN: 'hx168',
231       STATE_WEB: 'hx168_web',
232
233       show_role_list: false, // 显示选择角色
234       roleList: [],
235       roleId: '',
236       code: ''
237     }
238   },
239   watch: {
240     $route: {
241       handler: function(route) {
242         const query = route.query
243         if (query) {
244           this.redirect = query.redirect
245           this.otherQuery = this.getOtherQuery(query)
246         }
247       },
248       immediate: true
249     },
250
251     // 切换loginType
252     loginType: {
253       handler(loginType) {
254         this.$nextTick(() => {
255           if (loginType === 1) {
256             if (baseConfig.ismock) {
257               // this.$messageWarn('本地环境请使用密码登录')
258               // this.loginType = 0
259             } else {
260               if (!this.show_role_list) {
261                 if (!this.isTestView) this.initCodeLogin()
262               }
263             }
264           } else {
265             this.initLoginData()
266           }
267         })
268       },
269       immediate: true
270     }
271   },
272   mounted() {
273     this.init()
274   },
275   methods: {
276     init() {
277       this.loginType = this.isTestView ? 0 : 1
278       if (getQueryObj() && getQueryObj().loginType === '1') {
279         this.loginType = 1
280       }
281       if (this.$route.query.logout) {
282         // 清空企业微信登录code
283         this.replaceNoCode()
284         return
285       }
286       if (this.$route.query.logout_603) {
287         // 清空企业微信登录code,清空redirect
288         this.replaceNoCodeNoRedirect()
289         return
290       }
291       const code = getQueryObj().code
292       if (code) {
293         this.state = getQueryObj().state
294         this.code = code
295         this.$nextTick(() => {
296           this.codeLogin(code)
297         })
298       }
299     },
300
301     // 清空企业微信登录code
302     replaceNoCode() {
303       if (this.$route.query.isMiniprogram) { return }
304       window.location.replace('//' + window.location.host + window.location.pathname + '#/login?redirect=' + this.$route.query.redirect)
305     },
306
307     // 清空企业微信登录code,清空redirect
308     replaceNoCodeNoRedirect() {
309       if (this.$route.query.isMiniprogram) { return }
310       window.location.replace('//' + window.location.host + window.location.pathname + '#/login')
311     },
312
313     // 企业微信扫码登录 - 初始化
314     initCodeLogin() {
315       // 测试
316       // this.selectCodeLogin(window.prompt('请输入角色id'))
317       // return
318
319       // 测试回调
320       // this.wwLogin = new window.WwLogin({
321       //   'id': 'wx_reg',
322       //   'appid': 'wx23a7c266dcd048aa',
323       //   'agentid': '1000050',
324       //   'redirect_uri': 'http://test6.phiskin.com/assist/admin/employee/login/scanLogin',
325       //   'state': 'hx168',
326       //   'href': '',
327       //   'lang': 'zh'
328       // })
329
330       if (this.code) {
331         return
332       }
333
334       this.wwLogin = new window.WwLogin({
335         'id': 'wx_reg',
336         'appid': 'wx23a7c266dcd048aa',
337         'agentid': '1000050',
338         'redirect_uri': 'https://' + window.location.host + window.location.pathname,
339         // 'redirect_uri': 'http://serv3.phiskin.com/appointment/adminweb_v2/index.html',
340         // 'redirect_uri': 'http://test6.phiskin.com/adminwebV3/index.html', // 新版管理系统
341         'state': this.STATE_SCAN,
342         'href': '',
343         'lang': 'zh'
344       })
345     },
346
347     scanAgain() {
348       this.code = ''
349       this.show_role_list = false
350       if (this.loginType === 1) {
351         this.$nextTick(() => {
352           this.initCodeLogin()
353         })
354       } else {
355         this.loginType = 1
356       }
357     },
358
359     // 网页登录
360     handleWebLogin() {
361       let redirect_uri = 'https://' + window.location.host + window.location.pathname
362       redirect_uri = encodeURIComponent(redirect_uri)
363       const appid = 'wx23a7c266dcd048aa'
364       const response_type = 'code'
365       const scope = 'snsapi_base'
366       const state = this.STATE_WEB
367       const agentid = '1000050'
368
369       const loginUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirect_uri}&response_type=${response_type}&scope=${scope}&state=${state}&agentid=${agentid}#wechat_redirect`
370
371       window.location.replace(loginUrl)
372     },
373
374     // 扫码登录回调
375     codeLogin(code) {
376       const { state, STATE_SCAN, STATE_WEB } = this
377       let url = ''
378       if (state === STATE_SCAN) url = 'admin/employee/login/scanLogin'
379       if (state === STATE_WEB) url = 'admin/employee/login/webAuthLogin'
380
381       if (this.localOnline && this.isTestView) url = 'admin/employee/login/scanLogin' // 本地连线上 20230619 long
382
383       // state值不对,重新登录
384       if (!url) {
385         this.$alert('登录异常,请重新登录', '提示', {
386           confirmButtonText: '重新登录',
387           showClose: false,
388           callback: action => {
389             this.replaceNoCodeNoRedirect()
390           }
391         })
392         return
393       }
394
395       Req.http.post({
396         url: url,
397         udData: { noToken: true },
398         data: {
399           code, state
400         },
401         mockData: { 'code': '100', 'msg': 'SUCCESS', 'data': { 'roleList': [{ 'roleTypeId': '', 'createTime': { 'date': 22, 'hours': 17, 'seconds': 46, 'month': 8, 'timezoneOffset': -480, 'year': 121, 'minutes': 17, 'time': 1632302266607, 'day': 3 }, 'roleId': '82c1a5fe0a5011ec96245254007749be', 'roleName': '顾问', 'shopName': '新天地店', 'employeeId': '', 'roleUniqueStr': 'adviser_leader', 'id': '82c1a5fe0a5011ec96245254007749be', 'shopId': '605e391b620d11ebb06bb8599f4cafbe', 'oldId': '', 'isDel': 0 }, { 'roleTypeId': '', 'createTime': { 'date': 22, 'hours': 17, 'seconds': 46, 'month': 8, 'timezoneOffset': -480, 'year': 121, 'minutes': 17, 'time': 1632302266607, 'day': 3 }, 'roleId': '82c1a5fe0a5011ec96245254007749be', 'roleName': 'MIC', 'shopName': '新天地店', 'employeeId': '', 'roleUniqueStr': 'mic', 'id': '82c1ca2f0a5011ec96245254007749be', 'shopId': '605e391b620d11ebb06bb8599f4cafbe', 'oldId': '', 'isDel': 0 }, { 'roleTypeId': '', 'createTime': { 'date': 22, 'hours': 17, 'seconds': 46, 'month': 8, 'timezoneOffset': -480, 'year': 121, 'minutes': 17, 'time': 1632302266607, 'day': 3 }, 'roleId': '82c1a5fe0a5011ec96245254007749be', 'roleName': '医生', 'shopName': '新天地店', 'employeeId': '', 'roleUniqueStr': 'doctor', 'id': '82c1eb980a5011ec96245254007749be', 'shopId': '605e391b620d11ebb06bb8599f4cafbe', 'oldId': '', 'isDel': 0 }, { 'roleTypeId': '', 'createTime': { 'date': 22, 'hours': 17, 'seconds': 46, 'month': 8, 'timezoneOffset': -480, 'year': 121, 'minutes': 17, 'time': 1632302266607, 'day': 3 }, 'roleId': '82c1a5fe0a5011ec96245254007749be', 'roleName': '护士', 'shopName': '新天地店', 'employeeId': '', 'roleUniqueStr': 'nurse', 'id': '82c20cde0a5011ec96245254007749be', 'shopId': '605e391b620d11ebb06bb8599f4cafbe', 'oldId': '', 'isDel': 0 }, { 'roleTypeId': '', 'createTime': { 'date': 22, 'hours': 17, 'seconds': 46, 'month': 8, 'timezoneOffset': -480, 'year': 121, 'minutes': 17, 'time': 1632302266607, 'day': 3 }, 'roleId': '82c1a5fe0a5011ec96245254007749be', 'roleName': '前台', 'shopName': '新天地店', 'employeeId': '', 'roleUniqueStr': 'reception', 'id': '82c22d150a5011ec96245254007749be', 'shopId': '605e391b620d11ebb06bb8599f4cafbe', 'oldId': '', 'isDel': 0 }, { 'roleTypeId': '', 'createTime': { 'date': 22, 'hours': 17, 'seconds': 46, 'month': 8, 'timezoneOffset': -480, 'year': 121, 'minutes': 17, 'time': 1632302266607, 'day': 3 }, 'roleId': '82c1a5fe0a5011ec96245254007749be', 'roleName': '店长', 'shopName': '新天地店', 'employeeId': '', 'roleUniqueStr': 'shopowner', 'id': '82c24da90a5011ec96245254007749be', 'shopId': '605e391b620d11ebb06bb8599f4cafbe', 'oldId': '', 'isDel': 0 }, { 'roleTypeId': '', 'createTime': { 'date': 22, 'hours': 17, 'seconds': 46, 'month': 8, 'timezoneOffset': -480, 'year': 121, 'minutes': 17, 'time': 1632302266607, 'day': 3 }, 'roleId': '82c1a5fe0a5011ec96245254007749be', 'roleName': '护士助理', 'shopName': '新天地店', 'employeeId': '', 'roleUniqueStr': 'nurse_assistant', 'id': '82c26d510a5011ec96245254007749be', 'shopId': '605e391b620d11ebb06bb8599f4cafbe', 'oldId': '', 'isDel': 0 }, { 'roleTypeId': '', 'createTime': { 'date': 22, 'hours': 17, 'seconds': 46, 'month': 8, 'timezoneOffset': -480, 'year': 121, 'minutes': 17, 'time': 1632302266607, 'day': 3 }, 'roleId': '82c1a5fe0a5011ec96245254007749be', 'roleName': '医生助理', 'shopName': '新天地店', 'employeeId': '', 'roleUniqueStr': 'doctor_assistant', 'id': '82c28d7d0a5011ec96245254007749be', 'shopId': '605e391b620d11ebb06bb8599f4cafbe', 'oldId': '', 'isDel': 0 }], 'employeeId': '476051fc000711ecbbe230d0422e31b5' }}
402       }).then((inf) => {
403         // this.afterLogin(inf)
404         // 更改显示登录选项
405         this.roleList = inf.roleList
406         this.show_role_list = true
407         // 切换登录模式
408         this.loginType = 1
409       }).catch((res) => {
410         this.loading = false
411         this.code = '' // 清空关键判断
412         this.$messageError(res.msg)
413
414         // 去掉code参数,刷新页面
415         setTimeout(() => {
416           this.replaceNoCodeNoRedirect()
417         }, 1500)
418       })
419     },
420
421     // 选择角色
422     selectRole(id) {
423       this.roleId = id
424     },
425     // 选择角色后登录
426     selectCodeLogin(roleId) {
427       if (!roleId) {
428         this.$messageWarn('缺少选择角色id')
429         return
430       }
431       Req.http.post({
432         // 2022-06-23 登录新接口
433         url: 'admin/employee/login/selectLoginRoleNew',
434         // url: 'admin/employee/login/selectLoginRole',
435         udData: { noToken: true },
436         data: {
437           roleId
438         },
439         mockData: g_mockData.login
440       }).then((inf) => {
441         this.afterLogin(inf)
442       }).catch((res) => {
443         this.loading = false
444         this.$messageError(res.msg)
445       })
446     },
447
448     // 发送验证码
449     sendCode() {
450       if (!this.loginForm.username) return this.$message.error('请输入账号')
451       Req.http.post({
452         url: 'admin/employee/login/sendVerifyCode',
453         data: { account: this.loginForm.username },
454         mockData: {
455           code: 100,
456           msg: '',
457           data: {}
458         }
459       }).then((inf) => {
460         this.getCode()
461         this.$message.success('验证码发送成功')
462       })
463     },
464     // 倒计时
465     getCode() {
466       const times = 60 // 倒计时时间
467       if (!this.timer) {
468         this.secondCount = times
469         this.isShowCount = true
470         this.timer = setInterval(() => {
471           if (this.secondCount > 0 && this.secondCount <= times) {
472             this.secondCount--
473           } else {
474             this.isShowCount = false
475             clearInterval(this.timer)
476             this.timer = null
477           }
478         }, 1000)
479       }
480     },
481
482     // 密码登录 - 初始化
483     initLoginData() {
484       var loginData = localStorage.getItem('loginData')
485       // console.log(loginData)
486       // 获取保存的账号密码
487       if (loginData) this.loginForm = JSON.parse(loginData)
488
489       if (this.loginForm.username === '') {
490         this.$refs.username && this.$refs.username.focus()
491       } else if (this.loginForm.password === '') {
492         this.$refs.password && this.$refs.password.focus()
493       } else if (this.loginForm.safecode === '') {
494         this.$refs.safecode && this.$refs.safecode.focus()
495       }
496       if (this.isTestView) this.getSafeCodeImg()
497     },
498
499     // 是否大写
500     checkCapslock(e) {
501       const { key } = e
502       this.capsTooltip = key && key.length === 1 && (key >= 'A' && key <= 'Z')
503     },
504
505     // 切换密码显示
506     showPwd() {
507       if (this.passwordType === 'password') {
508         this.passwordType = ''
509       } else {
510         this.passwordType = 'password'
511       }
512       this.$nextTick(() => {
513         this.$refs.password.focus()
514       })
515     },
516
517     // 获取验证码图
518     getSafeCodeImg() {
519       var checkedId = this.getCheckedId()
520       Req.http.post({
521         url: 'admin/create/cheked',
522         data: { checkedId: checkedId },
523         udData: { noToken: true },
524         mockData: {
525           code: 100,
526           msg: '',
527           data: {
528             imgStr: 'xxxx'
529           }
530         }
531       }).then((inf) => {
532         this.safecodeImg = this.perfectSafeCode(inf.data.imgStr)
533         this.loginForm.checkedId = checkedId
534       })
535     },
536     // 补全验证码
537     perfectSafeCode(img) {
538       if (!img) return
539       return `data:image/jpeg;base64,${img}`
540     },
541     // 登录后回调
542     afterLogin(inf) {
543       // 保存登录凭证
544       setToken(inf.adminToken)
545
546       // 保存账号密码
547       var loginData = JSON.stringify({
548         username: this.loginForm.username.trim()
549       })
550       // password: this.loginForm.password.trim() // 20210322 long 取消记住密码
551       localStorage.setItem('loginData', loginData)
552
553       sessionStorage.setItem('newAppTime', new Date()) //  存入时间 用于获取新的预约数
554
555       // 保存用户数据
556       setUserData(inf)
557
558       this.loading = false
559
560       // 登录成功跳转页面
561       this.$messageSuc('登录成功')
562       setTimeout(() => {
563         // this.$router.push({ path: '/dashboard' })
564         this.$router.push({ path: this.redirect || '/dashboard', query: this.otherQuery })
565       }, 1000)
566     },
567     // 密码登录
568     handleLogin() {
569       this.$refs.loginForm.validate(valid => {
570         if (valid) {
571           const { username, password, safecode, checkedId } = this.loginForm
572           const params = {
573             account: username.trim(),
574             password: password.trim(),
575             checkedCode: safecode.trim()
576           }
577           this.loading = true
578           // const url = this.isTestView ? 'admin/employee/login/accountLogin' : 'admin/loginNew'
579           const url = this.isTestView ? 'admin/employee/login/accountLogin' : 'admin/employee/login/accountLogin/v2'
580           if (this.isTestView) {
581             params.checkedId = checkedId
582           }
583           Req.http.post({
584             // url: 'admin/loginNew',
585             url,
586             data: params,
587             udData: { noToken: true },
588             // mockData: g_mockData.login
589             mockData: g_mockData.scanLoginTest
590           }).then((inf) => {
591             this.loading = false
592             this.loginType = 1
593             this.jumpToRoomList()
594             // this.show_role_list = true
595             // this.roleList = inf.roleList || []
596             /* if (this.isTestView) {
597               this.loading = false
598               this.loginType = 1
599               this.show_role_list = true
600               this.roleList = inf.roleList || []
601             } else {
602               this.afterLogin(inf)
603             } */
604           }).catch((res) => {
605             this.loading = false
606             this.$messageError(res.msg)
607           })
608         } else {
609           console.log('表单验证失败')
610           return false
611         }
612       })
613     },
614     // 跳转房间列表
615     jumpToRoomList() {
616       this.$router.push({
617         path: `./room/list`
618       })
619     },
620     // 获取route query对象
621     getOtherQuery(query) {
622       return Object.keys(query).reduce((acc, cur) => {
623         if (cur !== 'redirect') {
624           acc[cur] = query[cur]
625         }
626         return acc
627       }, {})
628     },
629
630     // 测试服登录 👇
631     // 测试扫码登录
632     simulateLogin() {
633       this.loginType = 1
634       // 获取用户缓存权限信息
635       // const userData = JSON.parse(getUserData())
636       Req.http.post({
637         url: 'admin/employee/login/scanLoginTest',
638         data: {
639           employeeId: '476051fc000711ecbbe230d0422e31b5' // 黄嘉荣员工id 476051fc000711ecbbe230d0422e31b5
640           // employeeId: '3eb10b540b2b11ecb06bb8599f4cafbe' // 黄嘉荣员工id 3eb10b540b2b11ecb06bb8599f4cafbe - 和爷
641         },
642         mockData: g_mockData.scanLoginTest
643       }).then((res) => {
644         this.show_role_list = true
645         this.roleList = res.roleList || []
646       })
647     },
648
649     selectCodeLoginTest(id) {
650       let url = 'admin/employee/login/selectLoginRoleNewTest'
651       if (this.localOnline && this.isTestView) url = 'admin/employee/login/selectLoginRoleNew' // 本地连线上 20230619 long
652       Req.http.post({
653         url,
654         data: {
655           roleId: id
656         },
657         mockData: {
658           code: 100,
659           msg: '',
660           data: {
661             'adminToken': 'eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMzhlZjMzZjEyMzUxMWVkOTFkMTUyNTQwMGI4NTEwYSIsInN1YiI6ImxvZ2luX2FkbWluX2VtcGxveWVlIiwiaXNzIjoidXNlciIsImlhdCI6MTY3MzA4MTcwOSwiZXhwIjoxNjczMTI0MDA5fQ.s3QiYhK6EemOw9ksbxvM0jygnQxkHZwTWJ3JdAAFxkc',
662             'name': '黄嘉荣',
663             'tel': '15999971794',
664             'imgUrl': 'https://phiskin-pre-1305571091.cos.ap-shanghai.myqcloud.com/member/3a82bead-4960-44c1-915f-467df3a80cf3.jpg',
665             arr: [],
666             arrNew: [],
667             'employeeId': '476051fc000711ecbbe230d0422e31b5',
668             'shopId': 'bb4e8a7d620d11ebb06bb8599f4cafbe',
669             'roleName': 'admin',
670             'dataAuth': {
671               'warehouseList': [],
672               'noAttributionData': 0,
673               'roleId': '138ef33f123511ed91d1525400b8510a',
674               'dataList': [
675                 {
676                   'name': '静安店',
677                   'id': 'bb4e8a7d620d11ebb06bb8599f4cafbe'
678                 },
679                 {
680                   'name': '合肥店',
681                   'id': '66c581244ebb11edbebb525400b8510a'
682                 },
683                 {
684                   'name': '芙艾美容',
685                   'id': '2baa4ed774f111ecb4d45254007749be'
686                 },
687                 {
688                   'name': '倾选店',
689                   'id': '2bab614774f111ecb4d45254007749be'
690                 },
691                 {
692                   'name': '九方店',
693                   'id': '2bac145474f111ecb4d45254007749be'
694                 },
695                 {
696                   'name': '新天地店',
697                   'id': '605e391b620d11ebb06bb8599f4cafbe'
698                 },
699                 {
700                   'name': '静安国际及VIP门诊',
701                   'id': '973f9b28620e11ebb06bb8599f4cafbe'
702                 },
703                 {
704                   'name': '艾选店',
705                   'id': '66cb53b84ebb11edbebb525400b8510a'
706                 },
707                 {
708                   'name': '北京光华店',
709                   'id': '66ca982f4ebb11edbebb525400b8510a'
710                 },
711                 {
712                   'name': '东银店',
713                   'id': 'b88e3cd8620d11ebb06bb8599f4cafbe'
714                 },
715                 {
716                   'name': '杭州店',
717                   'id': 'b96aa6d1620d11ebb06bb8599f4cafbe'
718                 },
719                 {
720                   'name': '宁波海曙店',
721                   'id': 'b9fbfd79620d11ebb06bb8599f4cafbe'
722                 },
723                 {
724                   'name': '芙艾总部',
725                   'id': 'd685ff306ca54b1ea06b707fb0f57659'
726                 },
727                 {
728                   'name': '营销助手功能测试门店',
729                   'id': 'd4b9ace5a01911ecb4d45254007749be'
730                 },
731                 {
732                   'name': '古北店',
733                   'id': 'fc9f34d2994711ecb4d45254007749be'
734                 }
735               ]
736             },
737             'shopList': [
738               {
739                 'carWay': '',
740                 'clinicName': '',
741                 'code': '',
742                 'maxAppNum': 0,
743                 'city': '',
744                 'departmentId': '',
745                 'colorStr': '',
746                 'doctorRelaxTime': '',
747                 'editTime': {
748                   'date': 7,
749                   'hours': 16,
750                   'seconds': 10,
751                   'month': 0,
752                   'timezoneOffset': -480,
753                   'year': 123,
754                   'minutes': 55,
755                   'time': 1673081710058,
756                   'day': 6
757                 },
758                 'corpMpDepId': 0,
759                 'isUp': 0,
760                 'province': '',
761                 'subWay': '',
762                 'id': 'bb4e8a7d620d11ebb06bb8599f4cafbe',
763                 'addr': '',
764                 'institutionalCode': '',
765                 'apiId': '',
766                 'area': '',
767                 'sameTimeCustomerNum': 0,
768                 'shengMeiNum': 0,
769                 'workTime': '',
770                 'createTime': {
771                   'date': 7,
772                   'hours': 16,
773                   'seconds': 10,
774                   'month': 0,
775                   'timezoneOffset': -480,
776                   'year': 123,
777                   'minutes': 55,
778                   'time': 1673081710058,
779                   'day': 6
780                 },
781                 'maxSwitchNum': 0,
782                 'name': '静安店',
783                 'clinicCode': '',
784                 'isDel': 0
785               }
786             ],
787             'warehouseList': []
788           }
789         }
790       }).then((inf) => {
791         this.afterLogin(inf)
792       }).catch((res) => {
793         this.loading = false
794         this.$messageError(res.msg)
795       })
796     },
797
798     noop() {}
799   }
800 }
801 </script>
802
803 <style lang="scss">
804 /* 修复input 背景不协调 和光标变色 */
805 /* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
806
807 $bg:#283443;
808 $light_gray:#fff;
809 $gray_gray:#1B1E2F;
810 $cursor: #fff;
811
812 @supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
813   .login-container .el-input input {
814     color: $cursor;
815   }
816 }
817
818 /* reset element-ui css */
819 .login-container {
820   .el-input {
821     display: inline-block;
822     height: 47px;
823     width: 70%;
824
825     input {
826       background: transparent;
827       border: 0px;
828       -webkit-appearance: none;
829       border-radius: 0px;
830       padding: 12px 5px 12px 15px;
831       color: $gray_gray;
832       height: 47px;
833       caret-color: $gray_gray;
834
835       &:-webkit-autofill {
836         box-shadow: 0 0 0px 1000px #f0f1f6 inset !important;
837         -webkit-text-fill-color: $gray_gray !important;
838       }
839     }
840
841   }
842
843   .el-form-item {
844     border: 1px solid #2B3855;
845     // background: rgba(0, 0, 0, 0.1);
846     background: transparent;
847     border-radius: 22px;
848     color: #2B3855;
849   }
850 }
851 </style>
852
853 <style lang="scss" scoped>
854 $bg:#2d3a4b;
855 $dark_gray:#889aa4;
856 $light_gray:#eee;
857 $gray_gray:#2B3855;
858
859 .login-container {
860   min-height: 100vh;
861   width: 100vw;
862   position: relative;
863   overflow: hidden;
864   background: url('../../assets/login/login_left.png') 0 0 repeat-y, url('../../assets/login/login_mid.png') 15.2% 50% no-repeat,url('../../assets/login/login_right.png') 18% 0 no-repeat;
865   background-size: 15% auto, 15px auto, cover;
866   background-attachment: fixed;
867   .login-logo {
868     width: 40px;
869     height: 40px;
870   }
871
872   .login-form {
873     position: relative;
874     width: 85%;
875     max-width: 520px;
876     padding: 30px 35px 130px;
877     // padding: 160px 35px;
878     // padding: 0 25px;
879     margin: 0 auto;
880     // margin-top: 18vh;
881     // margin-left: 18%;
882     overflow: hidden;
883   }
884
885   .tips {
886     font-size: 14px;
887     color: #fff;
888     margin-bottom: 10px;
889
890     span {
891       &:first-of-type {
892         margin-right: 16px;
893       }
894     }
895   }
896
897   .svg-container {
898     padding: 6px 5px 6px 15px;
899     color: $dark_gray;
900     vertical-align: middle;
901     width: 30px;
902     display: inline-block;
903   }
904
905   .title-container {
906     position: relative;
907     margin-top: 100px;
908     .title {
909       font-size: 26px;
910       color: $gray_gray;
911       // margin: 0px auto 40px auto;
912       text-align: left;
913       font-weight: bold;
914     }
915   }
916
917   .show-pwd {
918     position: absolute;
919     right: 10px;
920     top: 7px;
921     font-size: 16px;
922     color: $dark_gray;
923     cursor: pointer;
924     user-select: none;
925   }
926
927   .safecode-img{
928     width: 80px;
929     height: 70%;
930     position: absolute;
931     right: 10px;
932     top: 50%;
933     transform: translateY(-50%);
934     font-size: 30px;
935     text-align: right;
936     color: $light_gray;
937     cursor: pointer;
938   }
939
940   .thirdparty-button {
941     position: absolute;
942     right: 0;
943     bottom: 6px;
944   }
945
946   @media only screen and (max-width: 470px) {
947     .thirdparty-button {
948       display: none;
949     }
950   }
951
952   // 企业微信扫码登录
953   #wx_reg{
954     padding: 30px 0 0;
955     border: 1px solid rgba(255, 255, 255, 0.1);
956     background: rgba(0, 0, 0, 0.1);
957     border-radius: 12px;
958     margin-bottom: 30px;
959     iframe{
960       width: 300px;
961       height: 300px;
962     }
963   }
964   .role-list-title{
965     color: $gray_gray;
966     margin-bottom: 20px;
967     text-align: center;
968     font-size: 18px;
969     font-weight: bold;
970     letter-spacing: 1px;
971   }
972   .role-list{
973     // margin-bottom: 20px;
974
975     .item{
976       box-sizing: border-box;
977       width: 47.5%;
978       margin-right: 5%;
979       padding: 10px 20px;
980       border: 1px solid $gray_gray;
981       background: transparent;
982       border-radius: 12px;
983       color: $gray_gray;
984       margin-bottom: 5%;
985       cursor: pointer;
986       transition: background .1s ease;
987       position: relative;
988
989       &:nth-child(2n){
990         margin-right: 0;
991       }
992
993       &:hover, &.active{
994         background: rgba(43, 56, 85, 0.8);
995         color: #fff;
996       }
997
998       .el-icon-check{
999         font-size: 24px;
1000         font-weight: bold;
1001         color: #99FFCC;
1002         transition: opacity .1s ease;
1003         opacity: 0;
1004         position: absolute;
1005         right: 10px;
1006         bottom: 5px;
1007       }
1008
1009       &.active .el-icon-check{
1010         opacity: 1;
1011       }
1012     }
1013
1014     &.block-list .item{
1015       margin-right: 0;
1016       width: 100%;
1017     }
1018
1019     .role-name{
1020       font-size: 16px;
1021       margin-bottom: 10px;
1022     }
1023
1024     .shop-name{
1025       font-size: 14px;
1026       // color: #aaa;
1027     }
1028   }
1029 }
1030 </style>