index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. <template>
  2. <view :style="colorStyle" class="wrapper">
  3. <view class="bag">
  4. <img :src="`../static/login-bg_${colorStatus}.jpg`" alt="" srcset="">
  5. </view>
  6. <view class="system-height" :style="{ height: statusBarHeight }"></view>
  7. <!-- #ifdef MP -->
  8. <view class="title-bar" style="height: 43px;">
  9. <view class="icon" @click="back" v-if="!isHome">
  10. <image src="../static/left.png"></image>
  11. </view>
  12. <view class="icon" @click="home" v-else>
  13. <image src="../static/home.png"></image>
  14. </view>
  15. {{$t(`商城登录`)}}
  16. </view>
  17. <!-- #endif -->
  18. <view class="merchant-msg">
  19. <img :src="configData.wap_login_logo" />
  20. <view class="name">
  21. {{configData.site_name}}
  22. </view>
  23. </view>
  24. <view class="wechat_login">
  25. <view class="btn-wrapper">
  26. <!-- #ifdef H5 -->
  27. <button hover-class="none" @click="wechatLogin" class="bg-theme btn1">{{$t(`微信登录`)}}</button>
  28. <!-- #endif -->
  29. <!-- #ifdef MP -->
  30. <template v-if="configData.wechat_auth_switch">
  31. <button class="bg-theme btn1" v-if="bindPhone" open-type="getPhoneNumber"
  32. @getphonenumber="getphonenumber">{{$t(`授权登录`)}}</button>
  33. <button class="bg-theme btn1" v-else-if="!bindPhone" @click="getAuthLogin">
  34. {{$t(`授权登录`)}}
  35. </button>
  36. </template>
  37. <button v-if="configData.phone_auth_switch" hover-class="none" @click="phoneLogin"
  38. class="btn2">{{$t(`手机号登录`)}}</button>
  39. <view class="cancel-login" @click="onReject">取消登录</view>
  40. <!-- #endif -->
  41. </view>
  42. </view>
  43. <view class="protocol" v-if="!canGetPrivacySetting">
  44. <checkbox-group @click.stop='ChangeIsDefault'>
  45. <checkbox :class="inAnimation?'trembling':''" @animationend='inAnimation=false'
  46. :checked="protocol ? true : false" /> <text @click.stop='ChangeIsDefault'>{{$t(`已阅读并同意`)}}</text>
  47. <text class="main-color" @click.stop="privacy(4)">{{$t(`《用户协议》`)}}</text>
  48. {{$t(`与`)}}<text class="main-color" @click.stop="privacy(3)">{{$t(`《隐私协议》`)}}</text>
  49. </checkbox-group>
  50. </view>
  51. <block v-if="isUp">
  52. <mobileLogin :isUp="isUp" :canClose="canClose" @close="maskClose" :authKey="authKey"
  53. @wechatPhone="wechatPhone"></mobileLogin>
  54. </block>
  55. <block v-if="isPhoneBox">
  56. <routinePhone :logoUrl="logoUrl" :isPhoneBox="isPhoneBox" @loginSuccess="bindPhoneClose" :authKey="authKey">
  57. </routinePhone>
  58. </block>
  59. <block>
  60. <editUserModal :isShow="isShow" @closeEdit="closeEdit" @editSuccess="editSuccess">
  61. </editUserModal>
  62. </block>
  63. <!-- #ifdef MP -->
  64. <privacyAgreementPopup v-if="canGetPrivacySetting" @onReject="onReject" @onAgree="onAgree">
  65. </privacyAgreementPopup>
  66. <!-- #endif -->
  67. </view>
  68. </template>
  69. <script>
  70. const app = getApp();
  71. let statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px';
  72. import mobileLogin from '../components/login_mobile/index.vue';
  73. import routinePhone from '../components/login_mobile/routine_phone.vue';
  74. import editUserModal from '@/components/eidtUserModal/index.vue'
  75. import privacyAgreementPopup from '@/components/privacyAgreementPopup/index.vue'
  76. import {
  77. getLogo,
  78. silenceAuth,
  79. routineBindingPhone,
  80. wechatAuthV2,
  81. authType,
  82. authLogin,
  83. wechatAuthLogin
  84. } from '@/api/public';
  85. import {
  86. LOGO_URL,
  87. EXPIRES_TIME,
  88. USER_INFO,
  89. STATE_R_KEY
  90. } from '@/config/cache';
  91. import {
  92. getUserInfo
  93. } from '@/api/user.js';
  94. import Routine from '@/libs/routine';
  95. import wechat from '@/libs/wechat';
  96. import colors from '@/mixins/color.js';
  97. import Auth from '@/libs/wechat.js';
  98. import {
  99. HTTP_REQUEST_URL
  100. } from '@/config/app';
  101. import {
  102. isWeixin
  103. } from "@/utils";
  104. import Cache from '@/utils/cache';
  105. export default {
  106. mixins: [colors],
  107. data() {
  108. return {
  109. imgHost: HTTP_REQUEST_URL,
  110. isUp: false,
  111. canClose: true,
  112. phone: '',
  113. statusBarHeight: statusBarHeight,
  114. isHome: false,
  115. isPhoneBox: false,
  116. protocol: true,
  117. isShow: false,
  118. isLogin: false,
  119. logoUrl: '',
  120. code: '',
  121. authKey: '',
  122. options: '',
  123. userInfo: {},
  124. codeNum: 0,
  125. canUseGetUserProfile: false,
  126. canGetPrivacySetting: false,
  127. inAnimation: false,
  128. colorStatus: uni.getStorageSync('color_status'),
  129. mp_is_new: this.$Cache.get('MP_VERSION_ISNEW') || false,
  130. configData: Cache.get('BASIC_CONFIG'),
  131. bindPhone: false
  132. };
  133. },
  134. components: {
  135. mobileLogin,
  136. routinePhone,
  137. editUserModal,
  138. privacyAgreementPopup
  139. },
  140. onLoad(options) {
  141. if(this.isLogin){
  142. uni.redirectTo({
  143. url: '/pages/index/index'
  144. });
  145. return;
  146. }
  147. if (uni.getUserProfile) {
  148. this.canUseGetUserProfile = true
  149. }
  150. // #ifdef MP
  151. if (wx.getPrivacySetting) {
  152. this.canGetPrivacySetting = true
  153. }
  154. // #endif
  155. let that = this;
  156. // #ifdef MP
  157. this.userLogin()
  158. // #endif
  159. // #ifdef H5
  160. const {
  161. code,
  162. state
  163. } = options;
  164. if (code) {
  165. let spread = this.$Cache.get("spread") || '';
  166. let agent_id = this.$Cache.get("agent_id") || '';
  167. let backUrl = state ? decodeURIComponent(state) : ''
  168. backUrl = "/pages/index/index";
  169. this.wechatAuthLogin({
  170. code:code,
  171. spread:spread,
  172. agent_id:agent_id,
  173. goods_user_type:state
  174. }, backUrl)
  175. }
  176. // #endif
  177. let pages = getCurrentPages();
  178. let prePage = pages[pages.length - 2];
  179. if (prePage && prePage.route == 'pages/order_addcart/order_addcart') {
  180. this.isHome = true;
  181. } else {
  182. this.isHome = false;
  183. }
  184. },
  185. methods: {
  186. wechatAuthLogin(d, back_url) {
  187. uni.showLoading({
  188. title: this.$t(`正在登录中`)
  189. });
  190. wechatAuthLogin(d).then(res => {
  191. uni.hideLoading();
  192. if (res.data.bindPhone) {
  193. this.authKey = res.data.key
  194. uni.navigateTo({
  195. url: `/pages/users/binding_phone/index?authKey=${this.authKey}&backUrl=${back_url}`
  196. })
  197. } else {
  198. let time = res.data.expires_time - this.$Cache.time();
  199. this.$store.commit('LOGIN', {
  200. token: res.data.token,
  201. time: time
  202. });
  203. this.getUserInfo(0, back_url)
  204. }
  205. }).catch(err => {
  206. uni.hideLoading();
  207. uni.reLaunch({
  208. url: '/pages/index/index'
  209. });
  210. uni.showToast({
  211. title: err,
  212. icon: 'none',
  213. duration: 2000
  214. });
  215. });
  216. },
  217. onAgree() {
  218. this.protocol = true
  219. },
  220. // 小程序 22.11.8日删除getUserProfile 接口获取用户昵称头像
  221. userLogin() {
  222. // if (!this.protocol) {
  223. // uni.showToast({
  224. // title: this.$t('请先阅读并同意协议'),
  225. // icon: 'none',
  226. // duration: 2000
  227. // });
  228. // return
  229. // }
  230. Routine.getCode()
  231. .then(code => {
  232. // uni.showLoading({
  233. // title: this.$t(`正在登录中`)
  234. // });
  235. authType({
  236. code,
  237. spread_spid: app.globalData.spid,
  238. spread_code: app.globalData.code,
  239. }).then(res => {
  240. uni.hideLoading();
  241. this.authKey = res.data.key;
  242. this.bindPhone = res.data.bindPhone
  243. // uni.navigateTo({
  244. // url: `/pages/users/binding_phone/index?authKey=${res.data.key}`
  245. // })
  246. })
  247. .catch(err => {
  248. uni.hideLoading();
  249. uni.showToast({
  250. title: err,
  251. icon: 'none',
  252. duration: 2000
  253. });
  254. });
  255. })
  256. .catch(err => {
  257. console.log(err)
  258. });
  259. },
  260. getAuthLogin() {
  261. if (!this.authKey) return
  262. if (!this.protocol) {
  263. uni.showToast({
  264. title: this.$t('请先阅读并同意协议'),
  265. icon: 'none',
  266. duration: 2000
  267. });
  268. return
  269. }
  270. uni.showLoading({
  271. title: this.$t(`正在登录中`)
  272. });
  273. authLogin({
  274. key: this.authKey
  275. }).then(res => {
  276. let time = res.data.expires_time - this.$Cache.time();
  277. this.$store.commit('LOGIN', {
  278. token: res.data.token,
  279. time: time
  280. });
  281. this.getUserInfo(res.data.bindName)
  282. }).catch(err => {
  283. uni.hideLoading();
  284. uni.showToast({
  285. title: err,
  286. icon: 'none',
  287. duration: 2000
  288. });
  289. });
  290. },
  291. ChangeIsDefault(e) {
  292. this.$set(this, 'protocol', !this.protocol);
  293. },
  294. editSuccess() {
  295. this.isShow = false
  296. },
  297. phoneLogin() {
  298. uni.navigateTo({
  299. url: `/pages/users/binding_phone/index?authKey=${this.authKey}&pageType=0`
  300. })
  301. },
  302. closeEdit() {
  303. this.isShow = false
  304. this.$util.Tips({
  305. title: this.$t(`登录成功`),
  306. icon: 'success'
  307. }, {
  308. tab: 3
  309. });
  310. },
  311. onReject() {
  312. uni.navigateBack();
  313. },
  314. // #ifdef MP
  315. back() {
  316. if (this.isLogin) {
  317. this.$store.commit('LOGIN', {
  318. token: '',
  319. time: 0
  320. });
  321. }
  322. uni.navigateBack();
  323. },
  324. // #endif
  325. // #ifndef MP
  326. back() {
  327. uni.navigateBack({
  328. delta: 1
  329. })
  330. },
  331. // #endif
  332. home() {
  333. uni.switchTab({
  334. url: '/pages/index/index'
  335. })
  336. },
  337. // 弹窗关闭
  338. maskClose(new_user) {
  339. this.isUp = false;
  340. // #ifdef MP
  341. if (new_user) {
  342. this.isShow = true
  343. }
  344. // #endif
  345. },
  346. bindPhoneClose(data) {
  347. this.isPhoneBox = false;
  348. if (data.isStatus) {
  349. // #ifdef MP
  350. this.getUserInfo(data.new_user)
  351. // #endif
  352. // #ifndef MP
  353. this.$util.Tips({
  354. title: this.$t(`登录成功`),
  355. icon: 'success'
  356. }, {
  357. tab: 3
  358. });
  359. // #endif
  360. }
  361. },
  362. // #ifdef MP
  363. // 小程序获取手机号码
  364. getphonenumber(e) {
  365. if (!this.protocol) {
  366. uni.showToast({
  367. title: this.$t('请先阅读并同意协议'),
  368. icon: 'none',
  369. duration: 2000
  370. });
  371. return
  372. }
  373. uni.showLoading({
  374. title: this.$t(`正在登录中`)
  375. });
  376. Routine.getCode()
  377. .then(code => {
  378. this.getUserPhoneNumber(e.detail.encryptedData, e.detail.iv, code);
  379. })
  380. .catch(error => {
  381. uni.$emit('closePage', false);
  382. uni.hideLoading();
  383. });
  384. },
  385. // 小程序获取手机号码回调
  386. getUserPhoneNumber(encryptedData, iv, code) {
  387. routineBindingPhone({
  388. encryptedData: encryptedData,
  389. iv: iv,
  390. code: code,
  391. spread_spid: app.globalData.spid,
  392. spread_code: app.globalData.code,
  393. agent_id: app.globalData.agent_id,
  394. key: this.authKey
  395. })
  396. .then(res => {
  397. let time = res.data.expires_time - this.$Cache.time();
  398. this.$store.commit('LOGIN', {
  399. token: res.data.token,
  400. time: time
  401. });
  402. // this.userInfo = res.data.userInfo;
  403. // this.$store.commit('SETUID', res.data.userInfo.uid);
  404. // this.$store.commit('UPDATE_USERINFO', res.data.userInfo);
  405. this.$Cache.clear('snsapiKey');
  406. this.getUserInfo(res.data.bindName)
  407. // this.$util.Tips({
  408. // title: this.$t(`登录成功`),
  409. // icon: 'success'
  410. // }, {
  411. // tab: 3
  412. // });
  413. })
  414. .catch(res => {
  415. uni.hideLoading();
  416. });
  417. },
  418. // #endif
  419. /**
  420. * 获取个人用户信息
  421. */
  422. getUserInfo(new_user, back_url) {
  423. let that = this;
  424. getUserInfo().then(res => {
  425. uni.hideLoading();
  426. that.userInfo = res.data;
  427. that.$store.commit('SETUID', res.data.uid);
  428. that.$store.commit('UPDATE_USERINFO', res.data);
  429. if (new_user) {
  430. this.isShow = true
  431. } else {
  432. // #ifdef MP
  433. that.$util.Tips({
  434. title: that.$t(`登录成功`),
  435. icon: 'success'
  436. }, {
  437. tab: 3
  438. });
  439. // #endif
  440. // #ifndef MP
  441. that.$util.Tips({
  442. title: that.$t(`登录成功`),
  443. icon: 'success'
  444. }, {
  445. tab: 4,
  446. url: back_url || '/pages/user/index'
  447. });
  448. // #endif
  449. }
  450. }).catch(err => {
  451. uni.hideLoading();
  452. uni.showToast({
  453. title: err.msg,
  454. icon: 'none',
  455. duration: 2000
  456. });
  457. });
  458. },
  459. privacy(type) {
  460. uni.navigateTo({
  461. url: "/pages/users/privacy/index?type=" + type
  462. })
  463. },
  464. // #ifdef H5
  465. // 获取url后面的参数
  466. getQueryString(name) {
  467. var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
  468. var reg_rewrite = new RegExp('(^|/)' + name + '/([^/]*)(/|$)', 'i');
  469. var r = window.location.search.substr(1).match(reg);
  470. var q = window.location.pathname.substr(1).match(reg_rewrite);
  471. if (r != null) {
  472. return unescape(r[2]);
  473. } else if (q != null) {
  474. return unescape(q[2]);
  475. } else {
  476. return null;
  477. }
  478. },
  479. // 公众号登录
  480. wechatLogin() {
  481. if (!this.protocol) {
  482. uni.showToast({
  483. title: this.$t('请先阅读并同意协议'),
  484. icon: 'none',
  485. duration: 2000
  486. });
  487. return
  488. }
  489. if (!this.code || this.options.scope !== 'snsapi_base') {
  490. this.$wechat.oAuth('snsapi_userinfo', location.href);
  491. } else {
  492. if (this.authKey) {
  493. // this.isUp = true;
  494. uni.navigateTo({
  495. url: `/pages/users/binding_phone/index?authKey=${this.authKey}`
  496. })
  497. }
  498. }
  499. },
  500. // 输入手机号后的回调
  501. wechatPhone() {
  502. this.$Cache.clear('snsapiKey');
  503. if (this.options.back_url) {
  504. let url = uni.getStorageSync('snRouter');
  505. url = url.indexOf('/pages/index/index') != -1 ? '/' : url;
  506. if (url.indexOf('/pages/users/wechat_login/index') !== -1) {
  507. url = '/';
  508. }
  509. if (!url) {
  510. url = '/pages/index/index';
  511. }
  512. this.isUp = false;
  513. uni.showToast({
  514. title: this.$t(`登录成功`),
  515. icon: 'none'
  516. });
  517. setTimeout(res => {
  518. location.href = url;
  519. }, 800);
  520. } else {
  521. this.isUp = false;
  522. uni.showToast({
  523. title: this.$t(`登录成功`),
  524. icon: 'none'
  525. });
  526. setTimeout(res => {
  527. location.href = '/pages/index/index';
  528. }, 800);
  529. }
  530. }
  531. // #endif
  532. }
  533. };
  534. </script>
  535. <style lang="scss">
  536. page {
  537. background: #fff;
  538. }
  539. .wrapper {
  540. position: relative;
  541. height: 100vh;
  542. .bag {
  543. position: absolute;
  544. top: 0;
  545. left: 0;
  546. width: 100%;
  547. opacity: .8;
  548. z-index: -1;
  549. /* #ifdef H5 */
  550. z-index: 0;
  551. /* #endif */
  552. img {
  553. width: 100%;
  554. height: 838rpx;
  555. }
  556. }
  557. .merchant-msg {
  558. padding-top: 252rpx;
  559. display: flex;
  560. justify-content: center;
  561. align-items: center;
  562. flex-direction: column;
  563. z-index: 2;
  564. /* #ifdef H5 */
  565. position: relative;
  566. /* #endif */
  567. img {
  568. width: 152rpx;
  569. height: 152rpx;
  570. border-radius: 50%;
  571. }
  572. .name {
  573. font-size: 40rpx;
  574. font-weight: 500;
  575. color: #333333;
  576. line-height: 56rpx;
  577. margin-top: 32rpx;
  578. }
  579. }
  580. }
  581. .wechat_login {
  582. margin-top: 96rpx;
  583. .img image {
  584. width: 100%;
  585. }
  586. .btn-wrapper {
  587. padding: 0 66rpx;
  588. button {
  589. width: 100%;
  590. height: 86rpx;
  591. line-height: 86rpx;
  592. margin-bottom: 40rpx;
  593. border-radius: 120rpx;
  594. font-size: 30rpx;
  595. &.btn1 {
  596. color: #fff;
  597. }
  598. &.btn2 {
  599. color: #666666;
  600. border: 1px solid #E4E4E4;
  601. margin-bottom: 30rpx;
  602. }
  603. }
  604. .cancel-login{
  605. color: #999;
  606. font-size: 28rpx;
  607. text-align: center;
  608. }
  609. }
  610. }
  611. .title-bar {
  612. position: relative;
  613. display: flex;
  614. align-items: center;
  615. justify-content: center;
  616. font-size: 34rpx;
  617. font-weight: 500;
  618. color: #333333;
  619. line-height: 48rpx;
  620. }
  621. .icon {
  622. position: absolute;
  623. left: 30rpx;
  624. top: 0;
  625. display: flex;
  626. align-items: center;
  627. justify-content: center;
  628. width: 80rpx;
  629. height: 80rpx;
  630. image {
  631. width: 50rpx;
  632. height: 50rpx;
  633. }
  634. }
  635. .protocol {
  636. position: fixed;
  637. bottom: 52rpx;
  638. left: 0;
  639. width: 100%;
  640. margin: 0 auto;
  641. color: #999999;
  642. font-size: 24rpx;
  643. line-height: 22rpx;
  644. text-align: center;
  645. bottom: calc(52rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
  646. bottom: calc(52rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
  647. .main-color {
  648. color: var(--view-theme);
  649. }
  650. .trembling {
  651. animation: shake 0.6s;
  652. }
  653. /deep/ uni-checkbox .uni-checkbox-input {
  654. width: 28rpx;
  655. height: 28rpx;
  656. }
  657. /deep/ uni-checkbox .uni-checkbox-input.uni-checkbox-input-checked::before {
  658. font-size: 24rpx
  659. }
  660. /deep/ uni-checkbox .uni-checkbox-wrapper {
  661. margin-bottom: 1px;
  662. }
  663. /*checkbox 选项框大小 */
  664. /deep/ checkbox .wx-checkbox-input {
  665. width: 28rpx;
  666. height: 28rpx;
  667. }
  668. /*checkbox选中后样式 */
  669. /deep/ checkbox .wx-checkbox-input.wx-checkbox-input-checked {
  670. background: white;
  671. }
  672. /*checkbox选中后图标样式 */
  673. /deep/ checkbox .wx-checkbox-input.wx-checkbox-input-checked::before {
  674. width: 28rpx;
  675. height: 28rpx;
  676. line-height: 28rpx;
  677. text-align: center;
  678. font-size: 22rpx;
  679. background: transparent;
  680. transform: translate(-50%, -50%) scale(1);
  681. -webkit-transform: translate(-50%, -50%) scale(1);
  682. }
  683. }
  684. </style>