index.vue 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. <template>
  2. <view class="login-box">
  3. <view class="login-title">登录</view>
  4. <view class="logo">
  5. <image src="@/static/login/logo.png" mode="aspectFit"></image>
  6. </view>
  7. <view class="desc">
  8. <image src="@/static/login/desc.png"></image>
  9. </view>
  10. <view class="form">
  11. <view class="form_item">
  12. <image class="img1" src="@/static/login/phone.png"></image>
  13. <input class="inp1" placeholder-class="pl" type="number" v-model="phone" placeholder="请输入手机号码" />
  14. </view>
  15. <view class="form_item">
  16. <image class="img1" src="@/static/login/password.png"></image>
  17. <input class="inp1" password="true" placeholder-class="pl" type="text" v-model="password" placeholder="请输入密码" />
  18. </view>
  19. </view>
  20. <view style="padding-top: 76rpx;">
  21. <button class="btn" @click="userLogin()">登录</button>
  22. </view>
  23. <view class="other-login" @click="getUserProfile()">
  24. <view class="ol-tilte">
  25. <text>快捷登录</text>
  26. </view>
  27. <div class="wx-login">
  28. <image src="@/static/login/weixin_icon.png" mode="aspectFit" />
  29. </div>
  30. </view>
  31. <image class="bottom_img" src="@/static/login/bottom_img.png" mode="widthFix" />
  32. <view class="popup-box" v-show="showPopup">
  33. <view class="login-popup">
  34. <view class="lp-top">
  35. <view class="lpt-left">
  36. <view class="title"> <text>登录</text> </view>
  37. <view class="tips"> <text>登录即可解锁更多权益</text> </view>
  38. </view>
  39. <view class="lpt-right" @click="showPopup=false">
  40. <image src="@/static/login/close_icon.png" mode="aspectFill"></image>
  41. </view>
  42. </view>
  43. <view class="lp-center">
  44. <view class="title">申请获取以下权限</view>
  45. <view class="tips">获得你的公开信息(昵称、头像等)</view>
  46. <view class="tips">获得你的手机号码</view>
  47. </view>
  48. <view class="lp-bottom">
  49. <!-- getUserInfo -->
  50. <button class="option-btn"
  51. open-type="getPhoneNumber"
  52. @getphonenumber="getPhoneNumber">
  53. 获取手机号
  54. </button>
  55. </view>
  56. </view>
  57. </view>
  58. </view>
  59. </template>
  60. <script>
  61. import {
  62. mapMutations
  63. } from 'vuex';
  64. export default {
  65. data() {
  66. return {
  67. phone: '',
  68. password: '',
  69. backpage: '',
  70. backtype: '',
  71. wxUserInfo: null, // 保存微信用户数据(临时)
  72. wxLoginInfo: {
  73. code: null,
  74. openid: null,
  75. session_key: null
  76. }, // 微信登录返回信息(临时)
  77. showPopup: false, // 获取电话弹窗
  78. }
  79. },
  80. onLoad(e) {
  81. this.backpage = e.backpage == undefined ? 'task' : e.backpage
  82. this.backtype = e.backtype == undefined ? 1 : e.backtype
  83. },
  84. methods: {
  85. ...mapMutations(['login']),
  86. /* 账号登录 */
  87. userLogin() {
  88. if (!(/^1[3456789]\d{9}$/.test(this.phone))) {
  89. uni.showToast({
  90. title: '请输入正确的手机号',
  91. icon: 'none'
  92. })
  93. return false;
  94. }
  95. if (this.password == '') {
  96. uni.showToast({
  97. title: '请输入密码',
  98. icon: 'none'
  99. })
  100. return false;
  101. }
  102. let params = {
  103. phone: this.phone,
  104. password: this.password,
  105. ip: ''
  106. }
  107. let that = this
  108. that.request("get","rider/wxLogin/loginRider",null,params).then(res => {
  109. if (res.code === 200) {
  110. that.login(res.data);
  111. uni.showToast({
  112. title: '登录成功',
  113. icon: 'none',
  114. duration: 1500
  115. })
  116. setTimeout(function() {
  117. that.loginBack(that.backpage, that.backtype)
  118. }, 1500)
  119. }
  120. })
  121. },
  122. /* 获取微信用户信息 */
  123. getUserProfile() {
  124. // #ifdef MP-WEIXIN
  125. let that = this;
  126. if(that.wxLoginInfo.openid) {
  127. // 已登录,但未获取手机号
  128. that.showPopup = true;
  129. }
  130. else if(uni.getUserProfile){
  131. // 未登录,且版本支持 uni.getUserProfile
  132. uni.getUserProfile({
  133. lang: 'zh_CN',
  134. desc: "获取您的昵称、头像、手机号",
  135. success: async(res) => {
  136. console.log('用户同意了授权', res)
  137. that.wxUserInfo = res.userInfo; // 临时保存微信用户基础数据
  138. that.mpWeixinTologin(); // 微信一键登录
  139. },
  140. fail:(err) => {
  141. console.log('授权失败:', err)
  142. uni.showToast({ title: err })
  143. }
  144. })
  145. } else {
  146. uni.showToast({ title: '当前版本过低' })
  147. }
  148. // #endif
  149. },
  150. /* 微信登录 */
  151. mpWeixinTologin() {
  152. let that = this;
  153. uni.login({
  154. provider: 'weixin',
  155. async success(res) {
  156. console.log('微信一键登录', res);
  157. if (res.errMsg == 'login:ok') {
  158. that.wxLoginInfo.code = res.code;
  159. that.serverLogin(1);
  160. }
  161. },
  162. fail(err) {
  163. console.log('uni.login', err);
  164. }
  165. });
  166. },
  167. /* 获取手机号 */
  168. getPhoneNumber(e) {
  169. console.log('获取手机号', e);
  170. let that = this;
  171. if(!that.wxLoginInfo.openid || !e.detail.encryptedData){
  172. return false; // 未登录
  173. }
  174. let content = {
  175. openid: that.wxLoginInfo.openid,
  176. sessionkey: that.wxLoginInfo.session_key,
  177. encryptedData: e.detail.encryptedData,
  178. iv: e.detail.iv,
  179. }
  180. let params = {
  181. raw: JSON.stringify(content)
  182. };
  183. that.request("get","rider/wxLogin/decryptS5",null,params).then(resolve => {
  184. //console.log('获取解密手机号', resolve)
  185. if (resolve.code === 200) {
  186. let content = {
  187. code: mpres.code,
  188. nickName: that.wxUserInfo.nickName,
  189. avatarUrl: that.wxUserInfo.avatarUrl
  190. };
  191. that.serverLogin(2);
  192. } else{
  193. uni.showToast({ title: resolve.msg })
  194. }
  195. })
  196. },
  197. /* 后台登录 */
  198. serverLogin(type){
  199. // type: 1-第一次后台登录(返回无token) 2-第一次后台登录(返回带token)
  200. let that = this;
  201. let content = {
  202. code: that.wxLoginInfo.code,
  203. phone: that.wxUserInfo.phone,
  204. nickName: that.wxUserInfo.nickName,
  205. avatarUrl: that.wxUserInfo.avatarUrl,
  206. openid : that.wxLoginInfo.openid,
  207. session_key : that.wxLoginInfo.session_key,
  208. };
  209. that.request("post","rider/wxLogin/wechatLogin",null,content).then(res => {
  210. console.log('获取数据库返回的用户信息', res);
  211. if (res.code === 200) {
  212. // 至此实际已登录
  213. that.wxLoginInfo.openid = res.data.openId;
  214. that.wxLoginInfo.session_key = res.data.sessionKey;
  215. // 保存数据库返回的用户信息
  216. if(type === 1){
  217. // 返回无token, 另需获取手机号绑定对应的openid
  218. that.showPopup = true; // 显示获取手机号按钮
  219. }
  220. else {
  221. // 返回带token, 进入订单页
  222. let duration = 1500; // 延迟跳转页面
  223. that.login(res.data); // 缓存用户数据token
  224. uni.showToast({ title: '登录成功', duration })
  225. setTimeout(() => {
  226. that.loginBack(that.backpage, that.backtype)
  227. }, duration)
  228. }
  229. }
  230. else{
  231. uni.showToast({ title: res.msg })
  232. }
  233. })
  234. }
  235. }
  236. }
  237. </script>
  238. <style lang="less" scoped>
  239. .login-box{
  240. position: relative;
  241. width: 100vw;
  242. height: 100vh;
  243. }
  244. .login-title {
  245. text-align: center;
  246. padding-top: 74rpx;
  247. font-size: 36rpx;
  248. color: #333333;
  249. font-weight: bold;
  250. }
  251. .logo {
  252. text-align: center;
  253. padding-top: 72rpx;
  254. image {
  255. width: 172rpx;
  256. height: 172rpx;
  257. }
  258. }
  259. .desc {
  260. text-align: center;
  261. padding-top: 48rpx;
  262. image {
  263. width: 284rpx;
  264. height: 46rpx;
  265. }
  266. }
  267. .form {
  268. width: 618rpx;
  269. margin: 0 auto;
  270. padding-top: 32rpx;
  271. .form_item {
  272. height: 100rpx;
  273. border-bottom: 2rpx solid #EFEFEF;
  274. position: relative;
  275. }
  276. .img1 {
  277. width: 36rpx;
  278. height: 40rpx;
  279. position: absolute;
  280. left: 26rpx;
  281. bottom: 28rpx;
  282. }
  283. .inp1 {
  284. width: 524rpx;
  285. display: inline-block;
  286. position: absolute;
  287. bottom: 0;
  288. height: 98rpx;
  289. left: 96rpx;
  290. /* color: #BBBBBB; */
  291. font-size: 30rpx;
  292. line-height: 98rpx;
  293. }
  294. .pl {
  295. color: #BBBBBB;
  296. font-size: 30rpx;
  297. }
  298. }
  299. .btn {
  300. width: 640rpx;
  301. height: 96rpx;
  302. line-height: 96rpx;
  303. color: #FFFFFF;
  304. background: linear-gradient(to right, #5095F4, #3662DD);
  305. font-size: 32rpx;
  306. border-radius: 8rpx;
  307. margin: 0 auto;
  308. }
  309. .other-login{
  310. position: relative;
  311. z-index: 5;
  312. width: 618rpx;
  313. margin: 80rpx auto 0;
  314. .ol-tilte{
  315. display: flex;
  316. align-items: center;
  317. justify-content: center;
  318. &:before,
  319. &:after{
  320. display: block;
  321. content: '';
  322. width: 30%;
  323. border-bottom: 2rpx solid #EFEFEF;
  324. }
  325. text{
  326. color: #666;
  327. font-size: 26rpx;
  328. padding: 0 20rpx;
  329. }
  330. }
  331. .wx-login{
  332. width: 88rpx;
  333. height: 88rpx;
  334. margin: 40rpx auto 0;
  335. image {
  336. display: block;
  337. width: 100%;
  338. height: 100%;
  339. }
  340. }
  341. }
  342. .bottom_img {
  343. position: absolute;
  344. left: 0;
  345. bottom: 0;
  346. display: block;
  347. width: 100%;
  348. }
  349. .popup-box{
  350. position: absolute;
  351. top: 0;
  352. left: 0;
  353. width: 100%;
  354. height: 100%;
  355. z-index: 10;
  356. background-color: rgba(0,0,0,.5);
  357. }
  358. .login-popup{
  359. position: absolute;
  360. left: 0;
  361. bottom: 0;
  362. width: 100%;
  363. z-index: 10;
  364. background-color: #fff;
  365. padding-bottom: 40rpx;
  366. .lp-top{
  367. display: flex;
  368. align-items: center;
  369. color: #000;
  370. line-height: 1.2;
  371. .lpt-left{
  372. flex: 1;
  373. padding: 30rpx;
  374. .title{
  375. font-size: 28rpx;
  376. font-weight: 500;
  377. }
  378. .tips{
  379. color: #9a9b9b;
  380. font-size: 18rpx;
  381. margin-top: 10rpx;
  382. }
  383. }
  384. .lpt-right{
  385. padding: 30rpx;
  386. image{
  387. display: block;
  388. width: 28rpx;
  389. height: 28rpx;
  390. }
  391. }
  392. }
  393. .lp-center{
  394. position: relative;
  395. padding: 10rpx 30rpx 40rpx;
  396. color: #000;
  397. &:after{
  398. position: absolute;
  399. bottom: 0;
  400. left: 30rpx;
  401. right: 30rpx;
  402. content: '';
  403. border-bottom: 1rpx solid #ededed;
  404. }
  405. .title{
  406. font-size: 28rpx;
  407. font-weight: 600;
  408. }
  409. .tips{
  410. font-size: 26rpx;
  411. margin-top: 10rpx;
  412. }
  413. }
  414. .lp-bottom{
  415. padding: 0 30rpx;
  416. margin-top: 40rpx;
  417. .option-btn{
  418. height: 86rpx;
  419. color: #fff;
  420. font-size: 22rpx;
  421. text-align: center;
  422. line-height: 86rpx;
  423. padding: 0 30rpx;
  424. background: linear-gradient(to right, #5095F4, #3662DD);
  425. }
  426. }
  427. }
  428. </style>