login.vue 15 KB

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