login.vue 19 KB

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