login.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. <template>
  2. <div>
  3. <div class="login-container" v-if="!forgotPwdFlag">
  4. <h2 class="title-big">登录</h2>
  5. <p class="title-name">欢迎来到二十一世纪英语智慧阅读平台</p>
  6. <div class="tabs-box">
  7. <a :class="[tabsIndex===0?'active':'']" @click="handleChangeTabs(0)">账号密码登录</a>
  8. <a :class="[tabsIndex===1?'active':'']" @click="handleChangeTabs(1)">验证码登录</a>
  9. </div>
  10. <!-- <template v-if="tabsIndex===0"> -->
  11. <el-form label-position="top" label-width="80px" ref="loginPwdForm" :model="loginPwdForm" class="form" :hide-required-asterisk="true" :rules="rulesPassword" v-show="tabsIndex===0">
  12. <el-form-item label="账号" prop="userName">
  13. <el-input v-model="loginPwdForm.userName" autocomplete="off" placeholder="用户名/邮箱/手机号" @blur="handleTrim('loginPwdForm','userName')" maxlength="100">
  14. </el-input>
  15. </el-form-item>
  16. <el-form-item label="密码" prop="password">
  17. <el-input v-model="loginPwdForm.password" :type="passwordFlag?'text':'password'" autocomplete="off" placeholder="请输入密码" @blur="handleTrim('loginPwdForm','password')" maxlength="20">
  18. <i slot="suffix" class="el-icon-view show-icon" @click="changeIcon('passwordFlag')" v-if="passwordFlag"></i>
  19. <i slot="suffix" class="show-icon" @click="changeIcon('passwordFlag')" v-else>
  20. <svg-icon icon-class="eye-invisible"></svg-icon>
  21. </i>
  22. </el-input>
  23. </el-form-item>
  24. <el-form-item prop="userAgreeCheck" class="userAgree-box">
  25. <el-checkbox-group v-model="loginPwdForm.userAgreeCheck">
  26. <el-checkbox label="1" name="userAgreeCheck"><a @click.prevent="lookUserAgreement">阅读并同意《用户协议》</a></el-checkbox>
  27. </el-checkbox-group>
  28. <a class="forgotPwd" @click="forgotPwd">忘记密码?</a>
  29. </el-form-item>
  30. <el-form-item class="btn-box">
  31. <el-button type="primary" @click="onSubmitPassword('loginPwdForm')" size="small" :loading="loading">登录</el-button>
  32. <el-button @click="onCancel('loginPwdForm')" size="small">取消</el-button>
  33. </el-form-item>
  34. </el-form>
  35. <!-- </template> -->
  36. <!-- <template v-if="tabsIndex===1"> -->
  37. <el-form label-position="top" label-width="80px" ref="loginCodeForm" :model="loginCodeForm" class="form" :hide-required-asterisk="true" :rules="rulesCode" v-show="tabsIndex===1">
  38. <el-form-item label="手机号" prop="phone">
  39. <el-input v-model="loginCodeForm.phone" autocomplete="off" placeholder="请输入完整手机号" @blur="handleTrim('loginCodeForm','phone')" maxlength="20">
  40. <template slot="prepend">+86</template>
  41. </el-input>
  42. </el-form-item>
  43. <el-form-item label="验证码" prop="code" class="code-box">
  44. <el-input v-model="loginCodeForm.code" autocomplete="off" placeholder="请输入验证码" class="code-input" @blur="handleTrim('loginCodeForm','code')" maxlength="20">
  45. </el-input>
  46. <el-button type="primary" @click="sendCode('time','phone','verificationCodeShow')" size="small" class="sendCode">
  47. {{ verificationCodeShow ? time+'s' : '发送验证码' }}
  48. </el-button>
  49. </el-form-item>
  50. <el-form-item prop="userAgreeCheck" class="userAgree-box">
  51. <el-checkbox-group v-model="loginCodeForm.userAgreeCheck">
  52. <el-checkbox label="1" name="userAgreeCheck"><a @click.prevent="lookUserAgreement">阅读并同意《用户协议》</a></el-checkbox>
  53. </el-checkbox-group>
  54. <a class="forgotPwd" @click="forgotPwd">忘记密码?</a>
  55. </el-form-item>
  56. <el-form-item class="btn-box">
  57. <el-button type="primary" @click="onSubmitPassword('loginCodeForm')" size="small" :loading="loading">登录</el-button>
  58. <el-button @click="onCancel('loginCodeForm')" size="small">取消</el-button>
  59. </el-form-item>
  60. </el-form>
  61. <!-- </template> -->
  62. </div>
  63. <forgot-pwd @cancelFot="cancelFot" v-if="forgotPwdFlag"></forgot-pwd>
  64. </div>
  65. </template>
  66. <script>
  67. import { getLogin } from "@/api/ajax";
  68. import { setToken } from "@/utils/auth";
  69. import ForgotPwd from "./forgotPwd.vue"
  70. export default {
  71. name: "login",
  72. props: ["toUrl","linkType"],
  73. components: { ForgotPwd },
  74. data() {
  75. const validatePhone = (rule, value, callback) => {
  76. if(this.tabsIndex===1){
  77. if (value === '') {
  78. callback(new Error('请输入手机号'));
  79. } else {
  80. let reg = /^1[3-9]\d{9}$/;
  81. let result = reg.test(value);
  82. if (result) {
  83. callback();
  84. } else {
  85. callback(new Error('请输入正确的手机号'));
  86. }
  87. }
  88. }
  89. };
  90. return {
  91. tabsIndex:0,
  92. loginPwdForm:{
  93. userName:'',
  94. password:'',
  95. userAgreeCheck: [],
  96. type: 'USER'
  97. },
  98. passwordFlag:false,
  99. rulesPassword:{
  100. userName:[
  101. { required: true, message: '请输入账号', trigger: 'blur' }
  102. ],
  103. password:[
  104. { required: true, message: '请输入密码', trigger: 'blur' }
  105. ],
  106. userAgreeCheck:[
  107. { type: 'array', required: true, message: '请阅读并同意《用户协议》', trigger: 'change' }
  108. ]
  109. },
  110. loginCodeForm:{
  111. phone:'',
  112. code:'',
  113. userAgreeCheck: [],
  114. type: 'USER'
  115. },
  116. rulesCode:{
  117. phone:[
  118. { required: true, validator: validatePhone, trigger: 'blur' }
  119. ],
  120. code:[
  121. { required: true, message: '请输入验证码', trigger: 'blur' }
  122. ],
  123. userAgreeCheck:[
  124. { type: 'array', required: true, message: '请阅读并同意《用户协议》', trigger: 'change' }
  125. ]
  126. },
  127. time: 60, //获取验证码的时间
  128. verificationCodeShow: false, //是否已经获取了验证码
  129. loading: false,
  130. timer: null,
  131. forgotPwdFlag: false
  132. };
  133. },
  134. watch: {
  135. },
  136. methods: {
  137. // 切换tabs
  138. handleChangeTabs(value){
  139. this.tabsIndex = value
  140. },
  141. changeIcon(flag){
  142. this[flag] = !this[flag]
  143. },
  144. // 查看用户协议
  145. lookUserAgreement(){
  146. },
  147. // 密码登录提交表单
  148. onSubmitPassword(formName){
  149. this.$refs[formName].validate((valid) => {
  150. if (valid) {
  151. this.loading = true
  152. let MethodName = "/OrgServer/LoginControl/Login";
  153. let data = null
  154. if(this.tabsIndex===0){
  155. data = {
  156. user_type:this.loginPwdForm.type,
  157. user_name:this.loginPwdForm.userName,
  158. password:this.loginPwdForm.password
  159. }
  160. }else{
  161. data = {
  162. user_type:this.loginCodeForm.type,
  163. user_name:this.loginCodeForm.phone,
  164. password:this.loginCodeForm.code,
  165. is_dynamic_verification_code_login:"true",
  166. dynamic_verification_code_send_type:"SMS"
  167. }
  168. }
  169. getLogin(MethodName, data)
  170. .then((res) => {
  171. this.loading = false
  172. setToken(res);
  173. if(this.toUrl){
  174. if(this.linkType==='url'){
  175. window.location.href = window.location.href.substring(0,window.location.href.indexOf('/#/'))+"/#" + this.toUrl
  176. window.location.reload()
  177. }else{
  178. this.$router.push({
  179. path: this.toUrl,
  180. });
  181. }
  182. }else{
  183. if(this.$route.path!=='/register'){
  184. window.location.reload()
  185. }else{
  186. this.$router.push({
  187. path: '/',
  188. });
  189. }
  190. }
  191. })
  192. .catch(() => {
  193. this.loading = false
  194. this.verificationCodeShow = false;
  195. clearInterval(this.timer);
  196. this.time = 60;
  197. });
  198. } else {
  199. return false;
  200. }
  201. });
  202. },
  203. // 取消 恢复到修改前状态
  204. onCancel(formName){
  205. this.$refs[formName].resetFields();
  206. this.$emit('cancelLogin')
  207. },
  208. // 发送验证码
  209. sendCode(time,phone,flag,obj){
  210. let this_ = this;
  211. if(this_[time] != 60){
  212. return
  213. }
  214. this_.timer = null;
  215. if (this_.loginCodeForm[phone]) {
  216. let reg = /^1[3-9]\d{9}$/;
  217. let result = reg.test(this_.loginCodeForm[phone]);
  218. if (!result) {
  219. this_.$message.warning('请输入正确的手机号');
  220. return
  221. }
  222. this_[flag] = true;
  223. this_.timer = setInterval(() => {
  224. this_[time]--;
  225. if (this_[time] == 0) {
  226. this_[flag] = false;
  227. clearInterval(this_.timer);
  228. this_.timer = null;
  229. this_[time] = 60;
  230. }
  231. }, 1000);
  232. let MethodName = "/OrgServer/LoginControl/SendVerificationCode";
  233. let data = {
  234. send_type: 'SMS',
  235. phone_or_email: this_.loginCodeForm.phone,
  236. };
  237. getLogin(MethodName, data).then((res) => {
  238. }).catch(()=>{
  239. this_[flag] = false;
  240. clearInterval(this_.timer);
  241. this_.timer = null;
  242. this_[time] = 60;
  243. });
  244. } else {
  245. this_.$message.warning('请先输入手机号');
  246. }
  247. },
  248. // 去掉前后空格
  249. handleTrim(form,fild){
  250. this[form][fild] = this[form][fild].trim()
  251. },
  252. // 忘记密码
  253. forgotPwd(){
  254. this.forgotPwdFlag = true
  255. },
  256. cancelFot(){
  257. this.forgotPwdFlag = false
  258. }
  259. },
  260. mounted() {
  261. },
  262. };
  263. </script>
  264. <style lang="scss" scoped>
  265. .login-container{
  266. background: #FFFFFF;
  267. padding: 64px 72px;
  268. .title-big{
  269. font-weight: 400;
  270. font-size: 32px;
  271. line-height: 40px;
  272. margin: 0;
  273. color: #1D2129;
  274. }
  275. .title-name{
  276. font-size: 14px;
  277. line-height: 22px;
  278. color: #86909C;
  279. margin: 0 0 40px 0;
  280. }
  281. .tabs-box{
  282. display: flex;
  283. a{
  284. font-size: 14px;
  285. line-height: 22px;
  286. color: #4E5969;
  287. border-radius: 100px;
  288. padding: 5px 16px;
  289. margin-right: 16px;
  290. &:hover{
  291. background: #F2F3F5;
  292. }
  293. &.active{
  294. background: #F2F3F5;
  295. font-weight: 500;
  296. color: #165DFF;
  297. }
  298. }
  299. }
  300. .form{
  301. margin-top: 40px;
  302. .show-icon{
  303. cursor: pointer;
  304. color: #4E5969;
  305. }
  306. .forgotPwd{
  307. font-size: 14px;
  308. line-height: 22px;
  309. color: #165DFF;
  310. }
  311. }
  312. }
  313. </style>
  314. <style lang="scss">
  315. .login-container{
  316. .form{
  317. .el-form-item__label{
  318. font-weight: 400;
  319. font-size: 14px;
  320. line-height: 22px;
  321. color: #4E5969;
  322. padding-bottom: 8px;
  323. }
  324. .userAgree-box{
  325. .el-form-item__content{
  326. display: flex;
  327. justify-content: space-between;
  328. line-height: 22px;
  329. }
  330. .el-checkbox-group{
  331. flex: 1;
  332. .el-checkbox{
  333. color: rgba(0, 0, 0, 0.88);
  334. font-weight: 400;
  335. }
  336. }
  337. }
  338. .btn-box{
  339. .el-button{
  340. width: 100%;
  341. }
  342. .el-button+.el-button{
  343. margin-left: 0;
  344. margin-top: 8px;
  345. }
  346. }
  347. .el-button--primary{
  348. background: #165DFF;
  349. border-color: #165DFF;
  350. border-radius: 2px;
  351. &:hover{
  352. background: #4080FF;
  353. border-color: #4080FF;
  354. }
  355. &:focus{
  356. background: #0E42D2;
  357. border-color: #0E42D2;
  358. }
  359. }
  360. .el-button--default{
  361. background: #F2F3F5;
  362. border-radius: 2px;
  363. border: none;
  364. color: #4E5969;
  365. &:hover{
  366. background: #E5E6EB;
  367. }
  368. &:focus{
  369. background: #C9CDD4;
  370. }
  371. }
  372. .code-box{
  373. .el-form-item__content{
  374. display: flex;
  375. }
  376. }
  377. .code-input{
  378. height: 32px;
  379. .el-input__inner{
  380. border-radius: 4px 0 0 4px;
  381. }
  382. }
  383. .sendCode{
  384. border-radius: 0 4px 4px 0;
  385. margin-top: 1px;
  386. width: 92px;
  387. flex-shrink: 0;
  388. }
  389. .el-form-item__content,.el-input__icon{
  390. line-height: 32px;
  391. color: #4E5969 !important;
  392. }
  393. .el-input__inner{
  394. height: 32px;
  395. color: #1D2129;
  396. background: #F2F3F5;
  397. border: none;
  398. }
  399. .el-textarea__inner,.el-input-group__prepend{
  400. color: #1D2129;
  401. }
  402. .el-checkbox__input.is-checked+.el-checkbox__label{
  403. color: #165DFF;
  404. }
  405. .el-checkbox__input.is-checked .el-checkbox__inner, .el-checkbox__input.is-indeterminate .el-checkbox__inner{
  406. background: #165DFF;
  407. border-color: #165DFF;
  408. }
  409. .el-input-group__prepend{
  410. width: 54px;
  411. height: 32px;
  412. border: none;
  413. background: #F2F3F5;
  414. border-radius: 2px 0px 0px 2px;
  415. line-height: 32px;
  416. text-align: center;
  417. padding: 0;
  418. }
  419. .el-input-group--prepend{
  420. display: flex;
  421. .el-input__inner{
  422. margin-left: 8px;
  423. flex: 1;
  424. }
  425. }
  426. }
  427. }
  428. </style>