login.vue 16 KB

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