login.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. <template>
  2. <view class="content">
  3. <view id="box" v-if="whichPage === '1'">
  4. <view id="top" class="">
  5. <view class="top_le"></view>
  6. <view class="top_ri"></view>
  7. </view>
  8. <view class="title2">
  9. <image
  10. src="/static/logintitle.png"
  11. mode=""
  12. style="width: 50%;height: 90%;"
  13. ></image>
  14. </view>
  15. <!--<view class="title">
  16. <view style="background: linear-gradient(to bottom, #33bae3 0%, #1d6fb5 100%); -webkit-background-clip: text;color: transparent;"
  17. >垃圾清运管理系统</view>
  18. </view>-->
  19. <view class="login-form">
  20. <u--form :model="inputForm" labelWidth="100px" labelPosition="left" :rules="rules" ref="uForm">
  21. <u-form-item label="手机号" borderBottom prop="username">
  22. <u-input border="none" v-model="inputForm.username" placeholder="请输入手机号"/>
  23. </u-form-item>
  24. <u-form-item label="验证码" borderBottom prop="loginPhoneCode">
  25. <u-input border="none" v-model="inputForm.loginPhoneCode" placeholder="请输入验证码"></u-input>
  26. <!--<u-button type="primary" @click="getLoginPushPhoneCode" :loading="!showLoginPhoneCode" style="background-color: #3595f9; width: 100px;">
  27. <span v-if="showLoginPhoneCode" style="color: white;">获取验证码</span>
  28. <span v-else class="count" style="color: white;">${loginCount} s</span>
  29. </u-button>-->
  30. <u-button type="primary" class="send" @click="getLoginPushPhoneCode" style="background-color: #3595f9; width: 100px;" :disabled="loginCounting">{{ loginCounting ? `请等待${loginCount}秒` : '获取验证码' }}</u-button>
  31. </u-form-item>
  32. <span class="count" style="color: #8f939c">{{this.randomCode}}</span>
  33. <!--<u-form-item label="密码" borderBottom prop="password">
  34. <u-input border="none" password v-model="inputForm.password" />
  35. </u-form-item>
  36. <u-form-item label="验证码" borderBottom prop="code" v-if="passwordErrorCount >= 5">
  37. <u-input border="none" v-model="inputForm.code" />
  38. <u&#45;&#45;image :showLoading="true" :src="captchaImg" width="140px" height="40px" @click="getCaptcha"></u&#45;&#45;image>
  39. </u-form-item>-->
  40. </u--form>
  41. </view>
  42. <view class="but">
  43. <u-button type="primary" shape="circle" color="linear-gradient(90deg, #1989FA, #19C2FA)" @click="bindLogin" text="立即登录"></u-button>
  44. </view>
  45. <view class="fot">
  46. <text @tap="loginOnPassword" style="color: #1989FA;">账号密码登陆</text>
  47. <text style="display: inline-block;width: 10vw;"></text>
  48. <text @tap="openForgetPassword" style="color: #1989FA;">忘记密码</text>
  49. </view>
  50. </view>
  51. <view id="box" v-else-if="whichPage === '3'">
  52. <view id="top" class="">
  53. <view class="top_le"></view>
  54. <view class="top_ri"></view>
  55. </view>
  56. <view class="title">
  57. <view>账号密码登陆</view>
  58. <!--<view>使用账号绑定的手机号找回密码</view>-->
  59. </view>
  60. <view class="login-form">
  61. <u--form :model="inputForm" labelWidth="100px" labelPosition="left" :rules="rules" ref="uForm">
  62. <u-form-item label="用户名" borderBottom prop="username">
  63. <u-input border="none" v-model="inputForm.username" />
  64. </u-form-item>
  65. <u-form-item label="密码" borderBottom prop="password">
  66. <u-input border="none" password v-model="inputForm.password" />
  67. </u-form-item>
  68. <u-form-item label="验证码" borderBottom prop="code">
  69. <u-input border="none" v-model="inputForm.code" />
  70. <u--image :showLoading="true" :src="captchaImg" width="140px" height="40px" @click="getCaptcha"></u--image>
  71. </u-form-item>
  72. </u--form>
  73. </view>
  74. <view class="but">
  75. <u-button type="primary" shape="circle" color="linear-gradient(90deg, #1989FA, #19C2FA)" @click="bindLogin" text="欢迎登录"></u-button>
  76. </view>
  77. <view class="fot">
  78. <!-- <text @tap="reg_ok">免费注册</text>-->
  79. <!-- <text style="display: inline-block;width: 10vw;"></text>-->
  80. <text @tap="backLogin" style="color: #1989FA;">返回登陆页面</text>
  81. </view>
  82. </view>
  83. <view id="box" v-else-if="whichPage === '2'">
  84. <view id="top" class="">
  85. <view class="top_le"></view>
  86. <view class="top_ri"></view>
  87. </view>
  88. <view class="title">
  89. <view>修改密码</view>
  90. <!--<view>使用账号绑定的手机号找回密码</view>-->
  91. </view>
  92. <view class="login-form">
  93. <u--form :model="inputForm" labelWidth="100px" labelPosition="left" :rules="rules" ref="uForm">
  94. <u-form-item label="绑定手机号" borderBottom prop="phoneNumber">
  95. <u-input border="none" v-model="inputForm.phoneNumber" placeholder='请输入绑定手机号'/>
  96. </u-form-item>
  97. <u-form-item label="验证码" borderBottom prop="phoneCode">
  98. <u-input border="none" v-model="inputForm.phoneCode" placeholder="请输入验证码"></u-input>
  99. <!--<u-button type="primary" @click="pushPhoneCode" :loading="!showPhoneCode" style="background-color: #3595f9; width: 100px;">
  100. <span v-if="showPhoneCode" style="color: white;">获取验证码</span>
  101. <span v-else class="count" style="color: white;">请等待 {{count}} s</span>
  102. </u-button>-->
  103. <u-button type="primary" class="send" @click="pushPhoneCode" style="background-color: #3595f9; width: 100px;" :disabled="counting">{{ counting ? `请等待${count}秒` : '获取验证码' }}</u-button>
  104. </u-form-item>
  105. <u-form-item label="新密码" borderBottom prop="newPassword" >
  106. <u-input border="none" v-model="inputForm.newPassword" placeholder='请输入新密码'/>
  107. </u-form-item>
  108. <u-form-item label="确认密码" borderBottom prop="newPasswordAgain" >
  109. <u-input border="none" v-model="inputForm.newPasswordAgain" placeholder='请输入确认密码'/>
  110. </u-form-item>
  111. </u--form>
  112. </view>
  113. <view class="but">
  114. <u-button type="primary" shape="circle" color="linear-gradient(90deg, #1989FA, #19C2FA)" @click="saveNewPass" text="保存"></u-button>
  115. </view>
  116. <view class="fot">
  117. <!-- <text @tap="reg_ok">免费注册</text>-->
  118. <!-- <text style="display: inline-block;width: 10vw;"></text>-->
  119. <text @tap="backLogin" style="color: #1989FA;">返回登陆页面</text>
  120. </view>
  121. </view>
  122. </view>
  123. </template>
  124. <script>
  125. import * as $auth from "@/common/auth.js"
  126. import loginService from "@/api/auth/loginService"
  127. import {mapActions} from 'vuex'
  128. var graceChecker = require("@/common/graceChecker.js");
  129. export default {
  130. data() {
  131. return {
  132. showPhoneCode: true,
  133. loginCount: 60, // 初始化 loginCount
  134. loginCounting: false, // 是否正在倒计时
  135. counting: false, // 是否正在倒计时
  136. count: 60, // 初始化 count
  137. timer: null, // 定时器
  138. showLoginPhoneCode: true,
  139. captchaImg: '',
  140. randomCode: '',
  141. inputForm: {
  142. 'username': '',
  143. 'password': '',
  144. 'code': '',
  145. 'uuid': '',
  146. 'phoneNumber': '',
  147. 'phoneCode': '',
  148. 'loginPhoneCode': '',
  149. 'newPassword': '',
  150. 'newPasswordAgain': '',
  151. },
  152. passwordErrorCount: 0,
  153. whichPage: '1', // 1为登录页面,2为忘记密码页面
  154. rules: {
  155. username: [
  156. {
  157. required: true,
  158. message: '请输入手机号',
  159. trigger: ['blur', 'change']
  160. }
  161. ],
  162. password: [
  163. {
  164. required: true,
  165. message: '请输入密码',
  166. trigger: ['blur', 'change']
  167. }
  168. ],
  169. code: [
  170. {
  171. required: true,
  172. message: '请输入验证码',
  173. trigger: ['blur', 'change']
  174. }
  175. ],
  176. phoneNumber: [
  177. {
  178. required: true,
  179. message: '请输入绑定手机号',
  180. trigger: ['blur', 'change']
  181. }
  182. ],
  183. loginPhoneCode: [
  184. {
  185. required: true,
  186. message: '请输入登录验证码',
  187. trigger: ['blur', 'change']
  188. }
  189. ],
  190. phoneCode: [
  191. {
  192. required: true,
  193. message: '请输入验证码',
  194. trigger: ['blur', 'change']
  195. }
  196. ],
  197. newPassword: [
  198. {
  199. required: true,
  200. message: '请输入新密码',
  201. trigger: ['blur', 'change']
  202. }
  203. ],
  204. newPasswordAgain: [
  205. {
  206. required: true,
  207. message: '请输入确认密码',
  208. trigger: ['blur', 'change']
  209. }
  210. ],
  211. }
  212. }
  213. },
  214. created() {
  215. this.getCaptcha()
  216. },
  217. methods: {
  218. ...mapActions(['refreshUserInfo']),
  219. // 登录
  220. bindLogin() {
  221. /**
  222. * 客户端对账号信息进行一些必要的校验。
  223. * 实际开发中,根据业务需要进行处理,这里仅做示例。
  224. */
  225. this.$refs.uForm.validate().then(res => {
  226. this.inputForm.openId = uni.getStorageSync('openId');
  227. loginService.login(this.inputForm).then((data) => {
  228. this.$store.commit('SET_TOKEN',data.token);
  229. this.refreshUserInfo();
  230. // uni.reLaunch({
  231. // url: '/pages/index/index',
  232. // });
  233. this.$router.push('/pages/index/index');
  234. }).catch(e => {
  235. // 密码错误次数增加
  236. this.passwordErrorCount++;
  237. // 如果密码错误次数超过5次,显示验证码
  238. if (this.passwordErrorCount >= 5) {
  239. this.inputForm.code = ''; // 清空验证码输入框
  240. this.getCaptcha(); // 获取验证码
  241. }
  242. this.getCaptcha()
  243. console.error(e)
  244. })
  245. })
  246. },
  247. // 获取验证码
  248. getCaptcha () {
  249. loginService.getCode().then((data) => {
  250. this.captchaImg = 'data:image/gif;base64,' + data.codeImg
  251. this.inputForm.uuid = data.uuid
  252. })
  253. },
  254. openForgetPassword () {
  255. console.log('进来了')
  256. this.inputForm.username = ''
  257. this.inputForm.password = ''
  258. this.inputForm.code = ''
  259. this.$nextTick(() => {
  260. this.whichPage = '2' // 打开忘记密码页面
  261. })
  262. },
  263. loginOnPassword () {
  264. this.inputForm.username = ''
  265. this.inputForm.password = ''
  266. this.inputForm.code = ''
  267. this.$nextTick(() => {
  268. this.whichPage = '3' // 打开账号密码页面
  269. })
  270. },
  271. backLogin () {
  272. this.inputForm.phoneNumber = ''
  273. this.inputForm.phoneCode = ''
  274. this.inputForm.loginPhoneCode = ''
  275. this.inputForm.newPassword = ''
  276. this.inputForm.newPasswordAgain = ''
  277. this.whichPage = '1' // 打开登录页面
  278. },
  279. getLoginPushPhoneCode () {
  280. this.randomCode = ""
  281. // 验证手机号码格式是否正确
  282. if (this.isNotEmpty(this.inputForm.username) && this.checkLoginMobile(this.inputForm.username)) {
  283. // 向手机号发送验证码
  284. loginService.getLoginPhoneCode(this.inputForm.username).then((data) => {
  285. if (data.success) {
  286. var randomCode = data.randomCode
  287. this.randomCode = "您本次登录的验证码为:" + randomCode
  288. uni.showToast({ title: data.message, icon: "success" });
  289. this.loginCounting = true;
  290. const timer = setInterval(() => {
  291. this.loginCount--;
  292. if (this.loginCount <= 0) {
  293. clearInterval(timer);
  294. this.loginCounting = false;
  295. this.loginCount = 60; // 重置倒计时时长
  296. }
  297. }, 1000);
  298. // ‘发送验证码’按钮倒计时
  299. /*const TIME_COUNT = 60 // 更改倒计时时间
  300. if (!this.timer) {
  301. this.loginCount = TIME_COUNT; // 设置倒计时初始值
  302. this.showLoginPhoneCode = false;
  303. this.timer = setInterval(() => {
  304. console.log("定时时间:",this.loginCount)
  305. if (this.loginCount > 0) {
  306. this.loginCount--;
  307. } else {
  308. this.showLoginPhoneCode = true;
  309. clearInterval(this.timer); // 清除定时器
  310. this.timer = null;
  311. }
  312. }, 1000);
  313. }*/
  314. } else {
  315. //this.$message.error(data.message)
  316. uni.showToast({
  317. title: data.message,
  318. icon: "none",
  319. duration: 2000 // 提示持续时间为1秒(1000毫秒)
  320. });
  321. }
  322. })
  323. } else {
  324. uni.showToast({
  325. title: '请填写正确的手机号',
  326. icon: "none",
  327. duration:2000
  328. })
  329. }
  330. },
  331. pushPhoneCode () {
  332. // 验证手机号码格式是否正确
  333. console.log('this.inputForm.phoneNumber', this.inputForm.phoneNumber)
  334. console.log('this.checkMobile(this.inputForm.phoneNumber)', this.checkMobile(this.inputForm.phoneNumber))
  335. if (this.isNotEmpty(this.inputForm.phoneNumber) && this.checkMobile(this.inputForm.phoneNumber)) {
  336. // 向手机号发送验证码
  337. loginService.getPhoneCode(this.inputForm.phoneNumber).then((data) => {
  338. if (data.success) {
  339. uni.showToast({ title: data.message, icon: "success" });
  340. // ‘发送验证码’按钮倒计时
  341. this.counting = true;
  342. const timer = setInterval(() => {
  343. this.count--;
  344. if (this.count <= 0) {
  345. clearInterval(timer);
  346. this.counting = false;
  347. this.count = 60; // 重置倒计时时长
  348. }
  349. }, 1000);
  350. /*const TIME_COUNT = 60 // 更改倒计时时间
  351. if (!this.timer) {
  352. this.count = TIME_COUNT
  353. this.showPhoneCode = false
  354. this.timer = setInterval(() => {
  355. if (this.count > 0 && this.count <= TIME_COUNT) {
  356. this.count--
  357. } else {
  358. this.showPhoneCode = true
  359. clearInterval(this.timer) // 清除定时器
  360. this.timer = null
  361. }
  362. }, 1000)
  363. }*/
  364. } else {
  365. this.$message.error(data.message)
  366. }
  367. })
  368. } else {
  369. uni.showToast({
  370. title: '请填写正确的手机号',
  371. icon: "none",
  372. duration:2000
  373. })
  374. }
  375. },
  376. checkLoginMobile (str) {
  377. const phone = /(^(\d{3,4}-)?\d{6,8}$)|(^(\d{3,4}-)?\d{6,8}(-\d{1,5})?$)|(^(((13[0-9]{1})|(15[0-9]{1})|(16[0-9]{1})|(18[0-9]{1})|(17[0-9]{1})|(19[0-9]{1}))+\d{8})$)/
  378. if (str && !phone.test(str)) {
  379. uni.showToast({
  380. title: '登陆手机号填写不正确,请重新填写',
  381. icon: "none",
  382. duration:2000
  383. })
  384. this.inputForm.username = ''
  385. return false;
  386. } else {
  387. return true;
  388. }
  389. },
  390. checkMobile (str) {
  391. const phone = /(^(\d{3,4}-)?\d{6,8}$)|(^(\d{3,4}-)?\d{6,8}(-\d{1,5})?$)|(^(((13[0-9]{1})|(15[0-9]{1})|(16[0-9]{1})|(18[0-9]{1})|(17[0-9]{1})|(19[0-9]{1}))+\d{8})$)/
  392. if (str && !phone.test(str)) {
  393. uni.showToast({
  394. title: '绑定手机号填写不正确,请重新填写',
  395. icon: "none",
  396. duration:2000
  397. })
  398. this.inputForm.phoneNumber = ''
  399. return false;
  400. } else {
  401. return true;
  402. }
  403. },
  404. isEmpty(value) {
  405. let result = false;
  406. if (value == null || value == undefined) {
  407. result = true;
  408. }
  409. if (typeof value == 'string' && (value.replace(/\s+/g, "") == "" || value == "")) {
  410. result = true;
  411. }
  412. if (typeof value == "object" && value instanceof Array && value.length === 0) {
  413. result = true;
  414. }
  415. return result;
  416. },
  417. isNotEmpty (value) {
  418. return !this.isEmpty(value)
  419. },
  420. saveNewPass () {
  421. return new Promise((resolve, reject) => {
  422. let errors = [];
  423. if (this.inputForm.newPassword !== this.inputForm.newPasswordAgain) {
  424. errors.push('两次输入的密码不相同,请重新输入!');
  425. }
  426. if (errors.length > 0) {
  427. // 存在错误,显示提示信息
  428. errors.forEach(error => {
  429. uni.showToast({
  430. title: error,
  431. icon: 'none',
  432. duration: 1500
  433. });
  434. });
  435. reject('Form validation failed');
  436. } else {
  437. loginService.savePwd(this.inputForm).then((data) => {
  438. if (data.success) {
  439. uni.showToast({
  440. title: data.message,
  441. icon: "success",
  442. duration: 1500 // 提示持续时间为1秒(1000毫秒)
  443. });
  444. this.inputForm.username = this.inputForm.phoneNumber
  445. this.inputForm.newPassword = this.inputForm.newPassword
  446. this.backLogin() // 修改密码成功后返回登录页面
  447. this.loading = false
  448. } else {
  449. uni.showToast({
  450. title: data.message,
  451. icon: 'none',
  452. duration: 1500
  453. });
  454. this.loading = false
  455. }
  456. }).catch(() => {
  457. this.loading = false
  458. })
  459. }
  460. });
  461. },
  462. }
  463. }
  464. </script>
  465. <style lang="scss" scoped>
  466. #box {
  467. position: relative;
  468. // color: $u-content-color;
  469. }
  470. .title {
  471. position: absolute;
  472. top: 35vh;
  473. width: 100vw;
  474. text-align: center;
  475. font-size: 28rpx;
  476. color: #198bfa;
  477. }
  478. .title2 {
  479. position: absolute;
  480. top: 10vh;
  481. width: 100vw;
  482. text-align: center;
  483. font-size: 28rpx;
  484. color: #198bfa;
  485. height: 200px;
  486. }
  487. .title view:nth-child(1) {
  488. height: 100px;
  489. font-size: 56rpx;
  490. font-family: PingFang SC;
  491. font-weight: bold;
  492. text-shadow: 0px 2px 24px rgba(58, 199, 118, 0.4);
  493. }
  494. .title view:nth-child(2) {
  495. font-size: 32rpx;
  496. font-family: PingFang SC;
  497. font-weight: 500;
  498. color: #198BFA;
  499. margin-top: 5vw;
  500. }
  501. #top {
  502. width: 100vw;
  503. height: 40vh;
  504. position: relative;
  505. }
  506. .top_ri {
  507. width: 100vw;
  508. height: 100vw;
  509. background: linear-gradient(141deg, #19C0FA 0%, #198BFA 100%);
  510. opacity: 0.1;
  511. border-radius: 50%;
  512. position: absolute;
  513. right: -47vw;
  514. top: -37vw;
  515. }
  516. .top_le {
  517. width: 100vw;
  518. height: 100vw;
  519. background: linear-gradient(141deg, #19C0FA 0%, #198BFA 100%);
  520. opacity: 0.1;
  521. border-radius: 50%;
  522. position: absolute;
  523. left: -34vw;
  524. top: -54vw;
  525. }
  526. .inp {
  527. padding-left: 5vw;
  528. position: relative;
  529. top: -4vh;
  530. }
  531. .inp text {
  532. font-size: 36rpx;
  533. font-family: PingFang SC;
  534. font-weight: 500;
  535. color: #333333;
  536. margin-left: 5px;
  537. }
  538. .but {
  539. padding-left: 50rpx;
  540. padding-right: 50rpx;
  541. margin-top: 60rpx;
  542. }
  543. .fot {
  544. width: 100vw;
  545. height: 26px;
  546. text-align: center;
  547. font-size: 28rpx;
  548. font-family: PingFang SC;
  549. font-weight: 500;
  550. color: #8E8E8E;
  551. margin-top: 20px;
  552. }
  553. .login-form {
  554. padding-left: 100rpx;
  555. padding-right: 30rpx;
  556. }
  557. </style>