login.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. <template>
  2. <view style="height: 100%">
  3. <image
  4. mode="widthFix"
  5. src="/pages4/static/login_bg.jpg"
  6. class="full_img"
  7. ></image>
  8. <u-navbar
  9. title="登录"
  10. :border-bottom="false"
  11. background="{ background: '#ffffff',opacity:0.4; }"
  12. title-color="#ffffff"
  13. back-icon-color="#ffffff"
  14. ></u-navbar>
  15. <view style="padding: 30rpx">
  16. <view style="width: 400rpx">
  17. <u-subsection
  18. @change="sectionChange"
  19. :list="list"
  20. :current="current"
  21. active-color="#007AFF"
  22. inactive-color="#ffffff"
  23. bg-color="rgba(255,255,255,0.52)"
  24. ></u-subsection>
  25. </view>
  26. <view class="login_box">
  27. <u-form :model="form" ref="uForm1" v-show="current == 0">
  28. <u-form-item prop="account"
  29. ><u-input
  30. type="idcard"
  31. v-model="form.account"
  32. placeholder-style="color:#999999"
  33. placeholder="手机号/学员身份证"
  34. /></u-form-item>
  35. <u-form-item prop="pwd"
  36. ><u-input
  37. class="password"
  38. v-model="form.pwd"
  39. placeholder-style="color:#999999"
  40. type="password"
  41. placeholder="登录密码"
  42. /></u-form-item>
  43. </u-form>
  44. <u-form :model="form" ref="uForm2" v-show="current == 1">
  45. <u-form-item prop="tel" ref="tel"
  46. ><u-input
  47. type="number"
  48. maxlength="11"
  49. placeholder-style="color:#999999"
  50. v-model="form.tel"
  51. placeholder="手机号"
  52. /></u-form-item>
  53. <u-form-item prop="code">
  54. <u-input
  55. v-model="form.code"
  56. type="number"
  57. placeholder-style="color:#999999"
  58. placeholder="验证码"
  59. />
  60. <u-button slot="right" size="mini" @click="getCode">{{
  61. codeTips
  62. }}</u-button>
  63. </u-form-item>
  64. </u-form>
  65. </view>
  66. <button
  67. class="loginBtn"
  68. :class="{ able: canLogin() }"
  69. @click="login"
  70. v-if="current == 0"
  71. >
  72. 登录
  73. </button>
  74. <button
  75. :disabled="isUse"
  76. :class="{ able: canLogin() }"
  77. class="loginBtn"
  78. @click="sms_login"
  79. v-if="current == 1"
  80. >
  81. 登录
  82. </button>
  83. <view style="width: 100%; margin: 40rpx auto">
  84. <view
  85. style="
  86. display: flex;
  87. align-items: center;
  88. color: #007aff;
  89. font-size: 24rpx;
  90. justify-content: center;
  91. "
  92. >
  93. <navigator
  94. hover-class="none"
  95. url="/pages2/register/register"
  96. style="margin: 0 40rpx"
  97. >立即注册</navigator
  98. >
  99. <view
  100. style="width: 3rpx; height: 20rpx; background-color: #007aff"
  101. ></view>
  102. <navigator
  103. hover-class="none"
  104. url="/pages2/register/forget"
  105. style="margin: 0 40rpx"
  106. >忘记密码</navigator
  107. >
  108. </view>
  109. </view>
  110. <view class="wxBtn">
  111. <button
  112. type="default"
  113. open-type="getPhoneNumber"
  114. @getphonenumber="wxLogin"
  115. class="wxloginBtn"
  116. ></button>
  117. <view
  118. style="
  119. text-align: center;
  120. color: #999999;
  121. font-size: 24rpx;
  122. margin-top: 10rpx;
  123. "
  124. >微信快捷登录</view
  125. >
  126. </view>
  127. </view>
  128. <u-verification-code
  129. seconds="60"
  130. ref="uCode"
  131. @change="codeChange"
  132. ></u-verification-code>
  133. </view>
  134. </template>
  135. <script>
  136. const PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
  137. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4qkbwIKErstK1sFESPEhOShpR
  138. pj4+sOVpJHxl5r/2xLBfA/MrXcAEra5Ro9cXNQSqmLLt8wecoLk/glfa5IdhXV0h
  139. RVQplIVs5z3MxcUa9ptKPHUTgh8xMCBvl8sUJKwkmn4vYWeDfHT22EL7Hr1pTMwU
  140. hF6WiNlWfQTVoF1rhwIDAQAB
  141. -----END PUBLIC KEY-----`;
  142. import JSEncrypt from "@/pages4/static/jsencrypt.min.js";
  143. export default {
  144. data() {
  145. return {
  146. code: "",
  147. form: {
  148. tel: "",
  149. code: "",
  150. account: "",
  151. pwd: "",
  152. },
  153. list: [
  154. {
  155. name: "密码登录",
  156. },
  157. {
  158. name: "短信登录",
  159. },
  160. ],
  161. rules: {
  162. tel: [
  163. {
  164. required: true,
  165. message: "请输入手机号",
  166. // 可以单个或者同时写两个触发验证方式
  167. trigger: ["change"],
  168. },
  169. {
  170. validator: (rule, value, callback) => {
  171. // 上面有说,返回true表示校验通过,返回false表示不通过
  172. // this.$u.test.mobile()就是返回true或者false的
  173. return this.$u.test.mobile(value);
  174. },
  175. message: "手机号码格式不正确",
  176. // 触发器可以同时用blur和change
  177. trigger: ["change"],
  178. },
  179. ],
  180. account: [
  181. {
  182. required: true,
  183. message: "请输入手机号/学员身份证",
  184. // 可以单个或者同时写两个触发验证方式
  185. trigger: ["change"],
  186. },
  187. ],
  188. pwd: [
  189. {
  190. required: true,
  191. message: "请输入密码",
  192. // 可以单个或者同时写两个触发验证方式
  193. trigger: ["change"],
  194. },
  195. ],
  196. code: [
  197. {
  198. required: true,
  199. message: "请输入验证码",
  200. // 可以单个或者同时写两个触发验证方式
  201. trigger: ["change"],
  202. },
  203. ],
  204. },
  205. current: 0,
  206. codeTips: "",
  207. isUse: false,
  208. isBack: false,
  209. };
  210. },
  211. onLoad(option) {
  212. this.$refs.uForm1.setRules(this.rules);
  213. this.$refs.uForm2.setRules(this.rules);
  214. if (option.isBack) {
  215. this.isBack = option.isBack;
  216. }
  217. let that = this;
  218. // this.from = option.from;
  219. uni.login({
  220. provider: "weixin",
  221. success: function (loginRes) {
  222. that.code = loginRes.code;
  223. },
  224. });
  225. },
  226. mounted() {},
  227. methods: {
  228. wxLogin(e) {
  229. console.log(e);
  230. this.$api
  231. .wxLogin({
  232. code: this.code,
  233. encryptedData: e.detail.encryptedData,
  234. iv: e.detail.iv,
  235. })
  236. .then((res) => {
  237. if (res.data.data.full_info) {
  238. //信息完善,直接进入页面
  239. uni.setStorageSync("user_account", res.data.data.user_account);
  240. uni.setStorageSync("token", res.data.data.token);
  241. this.$api.getInfo().then((resdata) => {
  242. if (resdata.data.code == 200) {
  243. this.$store.state.userInfo = resdata.data.data;
  244. if (!this.isBack) {
  245. let goPath = uni.getStorageSync("goPath");
  246. if (goPath == "course") {
  247. uni.redirectTo({
  248. url: "/pages2/wd/class",
  249. });
  250. this.$method.setUuid(new Date().valueOf() + "");
  251. } else if (goPath == "bank") {
  252. uni.redirectTo({
  253. url: "/pages2/wd/question_bank",
  254. });
  255. this.$method.setUuid(new Date().valueOf() + "");
  256. } else {
  257. uni.reLaunch({
  258. url: "/pages/index/index",
  259. });
  260. this.$method.setUuid(new Date().valueOf() + "");
  261. }
  262. } else {
  263. uni.navigateBack();
  264. }
  265. }
  266. });
  267. } else {
  268. //未完善信息,存为临时信息
  269. uni.setStorageSync("user_account_temp", res.data.data.user_account);
  270. uni.setStorageSync("token_temp", res.data.data.token);
  271. this.$navTo.togo("/pages2/register/bind");
  272. }
  273. });
  274. },
  275. canLogin() {
  276. if (this.current == 0) {
  277. if (this.form.account && this.form.pwd) {
  278. return true;
  279. }
  280. return false;
  281. } else if (this.current == 1) {
  282. if (this.form.tel && this.form.code) {
  283. return true;
  284. }
  285. return false;
  286. }
  287. },
  288. sms_login() {
  289. this.$refs.uForm2.validate((valid) => {
  290. if (valid) {
  291. let that = this;
  292. if (!this.form.tel) {
  293. this.$u.toast("请输入手机号码");
  294. return;
  295. }
  296. if (!this.form.code) {
  297. this.$u.toast("请输入验证码");
  298. return;
  299. }
  300. that.isUse = true;
  301. let datas = {
  302. tel: this.form.tel,
  303. code: this.form.code,
  304. };
  305. that.$api.smsLogin(datas).then(
  306. (res) => {
  307. that.isUse = false;
  308. if (res.data.code == 200) {
  309. if (res.data.data.full_info) {
  310. //信息完善,直接进入页面
  311. uni.setStorageSync(
  312. "user_account",
  313. res.data.data.user_account
  314. );
  315. uni.setStorageSync("token", res.data.data.token);
  316. that.$api.getInfo().then((resdata) => {
  317. if (resdata.data.code == 200) {
  318. that.$store.state.userInfo = resdata.data.data;
  319. if (!that.isBack) {
  320. let goPath = uni.getStorageSync("goPath");
  321. if (goPath == "course") {
  322. uni.redirectTo({
  323. url: "/pages2/wd/class",
  324. });
  325. } else if (goPath == "bank") {
  326. uni.redirectTo({
  327. url: "/pages2/wd/question_bank",
  328. });
  329. } else {
  330. uni.reLaunch({
  331. url: "/pages/index/index",
  332. });
  333. }
  334. } else {
  335. uni.navigateBack();
  336. }
  337. }
  338. });
  339. } else {
  340. //未完善信息,存为临时信息
  341. uni.setStorageSync(
  342. "user_account_temp",
  343. res.data.data.user_account
  344. );
  345. uni.setStorageSync("token_temp", res.data.data.token);
  346. that.$navTo.togo("/pages2/register/bind");
  347. }
  348. } else {
  349. that.$u.toast(res.data.msg);
  350. }
  351. },
  352. (err) => {
  353. that.isUse = false;
  354. }
  355. );
  356. }
  357. });
  358. },
  359. fakeLogin() {
  360. uni.setStorageSync("user_account", "123");
  361. uni.setStorageSync("token", "123");
  362. uni.switchTab({
  363. url: "/pages/index/index",
  364. });
  365. },
  366. /**
  367. *
  368. * @param {*} data
  369. * @returns
  370. * 加密
  371. */
  372. encryptor(data) {
  373. const encrypt = new JSEncrypt();
  374. encrypt.setPublicKey(PUBLIC_KEY);
  375. return encrypt.encrypt(data);
  376. },
  377. login() {
  378. let that = this;
  379. if (!this.form.account) {
  380. this.$u.toast("请输入手机号码/身份证号");
  381. return;
  382. }
  383. if (!this.form.pwd) {
  384. this.$u.toast("请输入密码");
  385. return;
  386. }
  387. //虚拟登录
  388. /* that.fakeLogin()
  389. return */
  390. that.isUse = true;
  391. let form = JSON.parse(JSON.stringify(this.form));
  392. form.pwd = this.encryptor(form.pwd);
  393. that.$api.accountLogin(form).then(
  394. (res) => {
  395. that.isUse = false;
  396. if (res.data.code == 200) {
  397. if (res.data.data.full_info) {
  398. //信息完善,直接进入页面
  399. uni.setStorageSync("user_account", res.data.data.user_account);
  400. uni.setStorageSync("token", res.data.data.token);
  401. that.$api.getInfo().then((resdata) => {
  402. if (resdata.data.code == 200) {
  403. that.$store.state.userInfo = resdata.data.data;
  404. if (!that.isBack) {
  405. uni.reLaunch({
  406. url: "/pages/index/index",
  407. });
  408. } else {
  409. uni.navigateBack();
  410. }
  411. }
  412. });
  413. } else {
  414. //未完善信息,存为临时信息
  415. uni.setStorageSync(
  416. "user_account_temp",
  417. res.data.data.user_account
  418. );
  419. uni.setStorageSync("token_temp", res.data.data.token);
  420. that.$navTo.togo("/pages2/register/bind");
  421. }
  422. } else {
  423. that.$u.toast(res.data.msg);
  424. }
  425. },
  426. (err) => {
  427. that.isUse = false;
  428. }
  429. );
  430. },
  431. codeChange(text) {
  432. this.codeTips = text;
  433. },
  434. // 获取验证码
  435. getCode() {
  436. let that = this;
  437. if (that.$refs.uCode.canGetCode) {
  438. if (that.$refs.tel.validateState == "success") {
  439. let datas = { tel: this.form.tel };
  440. that.$api.loginSms(datas).then(
  441. (res) => {
  442. if (res.data.code == 200) {
  443. that.$u.toast("验证码已发送");
  444. // 通知验证码组件内部开始倒计时
  445. that.$refs.uCode.start();
  446. } else {
  447. that.$u.toast(res.data.msg);
  448. }
  449. },
  450. (err) => {
  451. console.log(err);
  452. }
  453. );
  454. } else {
  455. this.$refs.tel.onFieldChange();
  456. }
  457. }
  458. },
  459. sectionChange(index) {
  460. this.current = index;
  461. },
  462. getPhoneNumber(e) {
  463. let that = this;
  464. uni.checkSession({
  465. success() {
  466. //session_key 未过期,并且在本生命周期一直有效
  467. that.putInfo(e);
  468. },
  469. fail() {
  470. // session_key 已经失效,需要重新执行登录流程
  471. uni.login({
  472. provider: "weixin",
  473. success: function (loginRes) {
  474. that.code = loginRes.code;
  475. that.putInfo(e);
  476. },
  477. });
  478. },
  479. });
  480. },
  481. putInfo(e) {
  482. let that = this;
  483. if (e.detail.encryptedData) {
  484. let inviteCode = uni.getStorageSync("inviteCode");
  485. //用户同意授权
  486. var datas = {
  487. iv: e.detail.iv,
  488. encryptedData: e.detail.encryptedData,
  489. code: that.code,
  490. };
  491. if (inviteCode) {
  492. datas.inviteCode = inviteCode;
  493. }
  494. that.$api.login(datas).then(
  495. (res) => {
  496. if (res.data.code == 200) {
  497. uni.setStorageSync("union_id", res.data.data.union_id);
  498. uni.setStorageSync("token", res.data.data.token);
  499. that.$api.getInfo().then((resdata) => {
  500. if (resdata.data.code == 200) {
  501. uni.navigateBack();
  502. that.$store.state.userInfo = resdata.data.data;
  503. }
  504. });
  505. } else {
  506. uni.showModal({
  507. title: "提示",
  508. content: res.data.msg,
  509. showCancel: false,
  510. });
  511. }
  512. },
  513. (err) => {
  514. console.log(err);
  515. }
  516. );
  517. }
  518. },
  519. },
  520. };
  521. </script>
  522. <style scoped lang="scss">
  523. .wxBtn {
  524. position: fixed;
  525. bottom: 10%;
  526. width: 100%;
  527. left: 0;
  528. }
  529. /deep/ .wxBtn button::after {
  530. border: none;
  531. }
  532. .loginBtn {
  533. width: 526rpx;
  534. height: 80rpx;
  535. background: linear-gradient(90deg, #015eea, #00c0fa);
  536. box-shadow: 0rpx 10rpx 16rpx 4rpx rgba(1, 99, 235, 0.04);
  537. opacity: 0.6;
  538. border-radius: 40rpx;
  539. color: #ffffff;
  540. text-align: center;
  541. line-height: 80rpx;
  542. margin: 40rpx auto;
  543. &.able {
  544. opacity: 1;
  545. }
  546. }
  547. .wxloginBtn {
  548. margin: 0 auto;
  549. background: url("/static/loginBtn.png") no-repeat;
  550. background-size: 100% 100%;
  551. border: none;
  552. width: 100rpx;
  553. height: 100rpx;
  554. }
  555. /deep/page {
  556. background-color: #ffffff;
  557. height: 100%;
  558. width: 100%;
  559. }
  560. .login_box {
  561. width: 100%;
  562. height: 360rpx;
  563. background: #ffffff;
  564. box-shadow: 0rpx 0rpx 16rpx 4rpx rgba(1, 99, 235, 0.1);
  565. border-radius: 24rpx;
  566. margin-top: 30rpx;
  567. padding: 40rpx 35rpx;
  568. .password {
  569. /deep/.uicon-eye-fill {
  570. &::before {
  571. color: #007aff;
  572. content: "\e613";
  573. }
  574. }
  575. }
  576. }
  577. /deep/ .u-item-bg {
  578. border-radius: 32px !important;
  579. }
  580. /deep/ .u-subsection {
  581. border-radius: 32px !important;
  582. }
  583. .full_img {
  584. position: absolute;
  585. left: 0;
  586. display: block;
  587. width: 100%;
  588. z-index: -999;
  589. top: 0;
  590. }
  591. .head {
  592. height: 96rpx;
  593. width: 100%;
  594. line-height: 96rpx;
  595. margin-top: 40rpx;
  596. text-align: center;
  597. display: flex;
  598. position: relative;
  599. justify-content: center;
  600. }
  601. .icon {
  602. position: absolute;
  603. left: 30rpx;
  604. }
  605. </style>