login.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  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. success: (result) => {
  299. if (result.confirm) {
  300. uni.setClipboardData({
  301. data: res.data.msg,
  302. success: function() {
  303. console.log('复制成功');
  304. }
  305. })
  306. } else if (result.cancel) {
  307. console.log('用户点击取消');
  308. }
  309. }
  310. });
  311. } else {
  312. that.$u.toast(res.data.msg);
  313. }
  314. },
  315. (err) => {
  316. that.isUse = false;
  317. }
  318. );
  319. }
  320. });
  321. },
  322. fakeLogin() {
  323. uni.setStorageSync("user_account", "123");
  324. uni.setStorageSync("token", "123");
  325. uni.switchTab({
  326. url: "/pages/index/index",
  327. });
  328. },
  329. /**
  330. *
  331. * @param {*} data
  332. * @returns
  333. * 加密
  334. */
  335. encryptor(data) {
  336. const encrypt = new JSEncrypt();
  337. encrypt.setPublicKey(PUBLIC_KEY);
  338. return encrypt.encrypt(data);
  339. },
  340. pwlogin() {
  341. let that = this;
  342. if (!this.form.account) {
  343. this.$u.toast("请输入手机号码/身份证号");
  344. return;
  345. }
  346. if (!this.form.pwd) {
  347. this.$u.toast("请输入密码");
  348. return;
  349. }
  350. if (this.isDualAuth) {
  351. if (!this.form.code) {
  352. this.$u.toast("请输入验证码");
  353. return;
  354. }
  355. this.form.tel = this.form.account;
  356. }
  357. //虚拟登录
  358. /* that.fakeLogin()
  359. return */
  360. that.isUse = true;
  361. let form = JSON.parse(JSON.stringify(this.form));
  362. form.pwd = this.encryptor(form.pwd);
  363. form["shareActivityCode"] = this.shareActivityCode;
  364. // 账号登录用户 /app/common/account_login
  365. that.$api.accountLogin(form).then(
  366. (res) => {
  367. that.isUse = false;
  368. if (res.data.code == 200) {
  369. // 记住账号
  370. uni.setStorageSync("rememberPwLoginMsg", {
  371. account: this.form.account,
  372. pwd: this.form.pwd,
  373. });
  374. this.loginCallback(res, "pwlogin");
  375. } else if (res.data.code == 699) {
  376. uni.showModal({
  377. title: '温馨提示',
  378. content: "系统升级中,您的账号需进入浏览器粘贴才能登录",
  379. success: (result) => {
  380. if (result.confirm) {
  381. uni.setClipboardData({
  382. data: res.data.msg,
  383. success: function() {
  384. console.log('复制成功');
  385. }
  386. })
  387. } else if (result.cancel) {
  388. console.log('用户点击取消');
  389. }
  390. }
  391. });
  392. } else {
  393. that.$u.toast(res.data.msg);
  394. }
  395. },
  396. (err) => {
  397. that.isUse = false;
  398. }
  399. );
  400. },
  401. codeChange(text) {
  402. this.codeTips = text;
  403. },
  404. // 获取验证码
  405. getCode(key) {
  406. let that = this;
  407. if (that.$refs.uCode.canGetCode) {
  408. if (that.$refs[key].validateState == "success") {
  409. let datas = {
  410. tel: this.form[key]
  411. };
  412. that.$api.loginSms(datas).then(
  413. (res) => {
  414. if (res.data.code == 200) {
  415. that.$u.toast("验证码已发送");
  416. // 通知验证码组件内部开始倒计时
  417. that.$refs.uCode.start();
  418. } else {
  419. that.$u.toast(res.data.msg);
  420. }
  421. },
  422. (err) => {
  423. console.log(err);
  424. }
  425. );
  426. } else {
  427. this.$refs[key].onFieldChange();
  428. }
  429. }
  430. },
  431. sectionChange(index) {
  432. this.current = index;
  433. // #ifdef H5
  434. if (index == 0) {
  435. const rememberPwLoginMsg = uni.getStorageSync("rememberPwLoginMsg");
  436. if (rememberPwLoginMsg) {
  437. let {
  438. account,
  439. pwd
  440. } = rememberPwLoginMsg;
  441. this.form.account = account;
  442. this.form.pwd = pwd;
  443. }
  444. }
  445. // #endif
  446. },
  447. getPhoneNumber(e) {
  448. let that = this;
  449. uni.checkSession({
  450. success() {
  451. //session_key 未过期,并且在本生命周期一直有效
  452. that.putInfo(e);
  453. },
  454. fail() {
  455. // session_key 已经失效,需要重新执行登录流程
  456. uni.login({
  457. provider: "weixin",
  458. success: function(loginRes) {
  459. that.code = loginRes.code;
  460. that.putInfo(e);
  461. },
  462. });
  463. },
  464. });
  465. },
  466. putInfo(e) {
  467. let that = this;
  468. if (e.detail.encryptedData) {
  469. let inviteCode = uni.getStorageSync("inviteCode");
  470. //用户同意授权
  471. var datas = {
  472. iv: e.detail.iv,
  473. encryptedData: e.detail.encryptedData,
  474. code: that.code,
  475. };
  476. if (inviteCode) {
  477. datas.inviteCode = inviteCode;
  478. }
  479. that.$api.login(datas).then(
  480. (res) => {
  481. if (res.data.code == 200) {
  482. uni.setStorageSync("union_id", res.data.data.union_id);
  483. uni.setStorageSync("token", res.data.data.token);
  484. that.$api.getInfo({
  485. fromPlat: 1
  486. }).then((resdata) => {
  487. if (resdata.data.code == 200) {
  488. uni.navigateBack();
  489. that.$store.state.userInfo = resdata.data.data;
  490. }
  491. });
  492. } else {
  493. uni.showModal({
  494. title: "提示",
  495. content: res.data.msg,
  496. showCancel: false,
  497. });
  498. }
  499. },
  500. (err) => {
  501. console.log(err);
  502. }
  503. );
  504. }
  505. },
  506. // 微信、密码、验证码 登录成功的回调
  507. loginCallback(res, types) {
  508. // if(res.data.data && res.data.data.full_info){
  509. uni.removeStorageSync("newUser_sc");
  510. uni.removeStorageSync("shareActivityCode");
  511. //信息完善,直接进入页面
  512. uni.setStorageSync("user_account", res.data.data.user_account);
  513. uni.setStorageSync("token", res.data.data.token);
  514. // 修改邀请码
  515. let sac = this.$store.getters.sac;
  516. sac &&
  517. this.$api.shareActivityCode({
  518. shareActivityCode: sac
  519. }).then((res) => {
  520. // if (res.data.code == 200) {
  521. // uni.removeStorageSync("sac");
  522. // }
  523. });
  524. // /app/user/getInfo 登录用户信息// fromPlat来源平台 1小程序 2PC网站
  525. this.$api.getInfo({
  526. fromPlat: 1
  527. }).then((resdata) => {
  528. if (resdata.data.code == 200) {
  529. this.$store.state.userInfo = resdata.data.data;
  530. if (this.bindForm.openId) {
  531. this.$api.openIdLogin({
  532. ...this.bindForm,
  533. userId: resdata.data.data.userId,
  534. });
  535. }
  536. //
  537. if (!this.isBack) {
  538. let goPath = "";
  539. if (types == "wxlogin" || types == "smslogin") {
  540. //密码登录不用判断电脑goPath, 直接到首页
  541. goPath = uni.getStorageSync("goPath");
  542. }
  543. if (goPath == "course") {
  544. uni.redirectTo({
  545. url: "/pages2/wd/class",
  546. });
  547. types == "wxlogin" &&
  548. this.$method.setUuid(new Date().valueOf() + "");
  549. } else if (goPath == "bank") {
  550. uni.redirectTo({
  551. url: "/pages2/wd/question_bank",
  552. });
  553. types == "wxlogin" &&
  554. this.$method.setUuid(new Date().valueOf() + "");
  555. } else {
  556. console.log("登录后跳转");
  557. uni.removeStorageSync("h5_code");
  558. uni.reLaunch({
  559. url: "/pages/index/index?show=1",
  560. });
  561. types == "wxlogin" &&
  562. this.$method.setUuid(new Date().valueOf() + "");
  563. }
  564. } else {
  565. uni.navigateBack();
  566. }
  567. }
  568. });
  569. },
  570. async quickLogin() {
  571. let openId = await getOpenid();
  572. let res = await this.$api.openIdLogin({
  573. openId
  574. });
  575. if (res.data.code === 200) {
  576. this.loginCallback(res);
  577. } else {
  578. this.bindForm = {
  579. openId,
  580. unionId: uni.getStorageSync("unionId")
  581. };
  582. uni.showToast({
  583. icon: "none",
  584. title: res.data.msg + "请用密码或验证码登录!",
  585. });
  586. }
  587. },
  588. },
  589. };
  590. </script>
  591. <style scoped lang="scss">
  592. .wxBtn {
  593. position: fixed;
  594. bottom: 10%;
  595. width: 100%;
  596. left: 0;
  597. .wxBtn_title {
  598. display: flex; //生成浏览器兼容性代码
  599. width: 70%;
  600. margin: 0 auto 48rpx;
  601. .line {
  602. flex: 1;
  603. position: relative;
  604. top: -16rpx;
  605. border-bottom: 2rpx solid #d9d9d9;
  606. }
  607. .text {
  608. padding: 0 28rpx;
  609. font-size: 28rpx;
  610. color: #666666;
  611. }
  612. }
  613. .wxloginBtn {
  614. margin: 0 auto;
  615. width: 100rpx;
  616. height: 100rpx;
  617. background: #66c8f9;
  618. border-radius: 50%;
  619. border: none;
  620. padding: 0;
  621. image {
  622. width: 64rpx;
  623. height: 64rpx;
  624. }
  625. }
  626. }
  627. /deep/ .wxBtn button::after {
  628. border: none;
  629. }
  630. .loginBtn {
  631. width: 526rpx;
  632. height: 80rpx;
  633. background: linear-gradient(90deg, #015eea, #00c0fa);
  634. box-shadow: 0rpx 10rpx 16rpx 4rpx rgba(1, 99, 235, 0.04);
  635. opacity: 0.6;
  636. border-radius: 40rpx;
  637. color: #ffffff;
  638. text-align: center;
  639. line-height: 80rpx;
  640. margin: 40rpx auto;
  641. &.able {
  642. opacity: 1;
  643. }
  644. }
  645. /deep/page {
  646. background-color: #ffffff;
  647. height: 100%;
  648. width: 100%;
  649. }
  650. .login_box {
  651. width: 100%;
  652. height: 360rpx;
  653. background: #ffffff;
  654. box-shadow: 0rpx 0rpx 16rpx 4rpx rgba(1, 99, 235, 0.1);
  655. border-radius: 24rpx;
  656. margin-top: 30rpx;
  657. padding: 40rpx 35rpx;
  658. .password {
  659. /deep/.uicon-eye-fill {
  660. &::before {
  661. color: #007aff;
  662. content: "\e613";
  663. }
  664. }
  665. }
  666. }
  667. /deep/ .u-item-bg {
  668. border-radius: 32px !important;
  669. }
  670. /deep/ .u-subsection {
  671. border-radius: 32px !important;
  672. }
  673. .full_img {
  674. position: absolute;
  675. left: 0;
  676. display: block;
  677. width: 100%;
  678. z-index: -999;
  679. top: 0;
  680. }
  681. .head {
  682. height: 96rpx;
  683. width: 100%;
  684. line-height: 96rpx;
  685. margin-top: 40rpx;
  686. text-align: center;
  687. display: flex;
  688. position: relative;
  689. justify-content: center;
  690. }
  691. .icon {
  692. position: absolute;
  693. left: 30rpx;
  694. }
  695. </style>