login.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. <template>
  2. <view class="" :style="vuex_skin">
  3. <!-- #ifdef MP-WEIXIN -->
  4. <!-- 获取手机号 -->
  5. <u-popup v-model="phoneShow" mode="center" border-radius="14" width="70%">
  6. <view class="" style="padding: 30rpx 50rpx 0;">
  7. <view class="center">
  8. <text class="text-bold">授权手机号</text>
  9. </view>
  10. <view style="padding: 80rpx 0;">
  11. <view class=" margin-bottom-20 text-sm text-center" style="line-height: 42rpx;">
  12. <text style="color: #949494;">为了保证用户评选公平,大赛采用实名制投票,需要授权获取您的手机号</text>
  13. </view>
  14. </view>
  15. <view class="flex justify-around">
  16. <button @click="phoneShow=false" class="cu-btn radius bg-gray "
  17. style="height: 60rpx;margin-bottom: 20rpx;font-size: 24rpx;">
  18. 暂不授权
  19. </button>
  20. <button class="cu-btn bg-base radius" style="height: 60rpx;margin-bottom: 20rpx;font-size: 24rpx;"
  21. open-type="getPhoneNumber" @getphonenumber="getphonenumber">
  22. 确定授权
  23. </button>
  24. </view>
  25. </view>
  26. </u-popup>
  27. <!-- 获取头像昵称 -->
  28. <view @touchmove.stop.prevent="clear" v-show="dialogShow">
  29. <view class="popup_mask" @touchmove.stop.prevent="clear"></view>
  30. <view class="">
  31. <view class="dt-login-wrap">
  32. <view class="title">请先登录</view>
  33. <view class="content">
  34. <view class="userinfo-avatar">
  35. <open-data type="userAvatarUrl"></open-data>
  36. </view>
  37. <open-data type="userNickName"></open-data>
  38. <text class="subtitle">申请获取您的公开信息(昵称,头像)</text>
  39. </view>
  40. <view class="btn-content setBtnCss">
  41. <button @click="hide" style="padding: 10rpx 0;">暂不登录</button>
  42. <button @click="getUserProfile" style="padding: 10rpx 0;">立即登录</button>
  43. <!-- <button v-else open-type="getUserInfo" @getuserinfo="getuserinfo">立即登录</button> -->
  44. </view>
  45. </view>
  46. </view>
  47. </view>
  48. <!-- #endif -->
  49. <!-- #ifndef MP-WEIXIN -->
  50. <view @touchmove.stop.prevent="clear" v-show="dialogShow">
  51. <view class="popup_mask" @touchmove.stop.prevent="clear"></view>
  52. <view class="">
  53. <view class="dt-login-wrap">
  54. <view class="title">请先登录</view>
  55. <view class="content" style="padding: 120rpx 30rpx ;">
  56. <u-form :model="form" ref="uForm" label-width="140" :border-bottom="borderBottom">
  57. <u-form-item label="手机号">
  58. <u-input v-model="form.phone" :clearable="false" />
  59. </u-form-item>
  60. <u-form-item label="验证码">
  61. <u-input v-model="form.code" :clearable="false" />
  62. </u-form-item>
  63. </u-form>
  64. <view class="text-sm text-gray margin-top-10 text-left">
  65. <text style="color: #EF9944;">* 未注册过的手机号,点击登录时我们会给您创建一个新的账号</text>
  66. </view>
  67. </view>
  68. <view class="btn-content setBtnCss "
  69. style="background-color: #FFFFFF;border-radius: 20rpx;border-top: 1rpx solid #f4f4f4;">
  70. <button @click="hide" style="padding: 5rpx 0;border-right: 1rpx solid #f4f4f4;">暂不登录</button>
  71. <button @click="h5Login" style="padding: 5rpx 0;">立即登录</button>
  72. </view>
  73. </view>
  74. </view>
  75. </view>
  76. <!-- #endif -->
  77. <toast ref="toast"></toast>
  78. </view>
  79. </template>
  80. <script>
  81. import pointAuth from "./alert/pointAuth.vue"
  82. export default {
  83. name: "login",
  84. components: {
  85. pointAuth
  86. },
  87. data() {
  88. return {
  89. borderBottom: false,
  90. notToast: false,
  91. canIUseGetUserProfile: false,
  92. //保存时间七天
  93. cacheTime: 1 * 24 * 60 * 60 * 7,
  94. dialogShow: false,
  95. jscode: '',
  96. //邀请码
  97. inviteCode: '',
  98. userInfo: '',
  99. sessionKey: '',
  100. //获取手机号
  101. phoneShow: false,
  102. //h5登录
  103. form: {
  104. phone: '',
  105. code: ''
  106. }
  107. };
  108. },
  109. beforeDestroy() {
  110. if (this.timer) {
  111. clearTimeout(this.timer)
  112. this.timer = null
  113. }
  114. },
  115. created() {
  116. if (uni.getUserProfile) {
  117. this.canIUseGetUserProfile = false
  118. }
  119. },
  120. methods: {
  121. async h5Login() {
  122. if (this.$isEmpty(this.form.phone)) {
  123. this.$u.toast("请输入手机号")
  124. return
  125. }
  126. if (this.$isEmpty(this.form.code)) {
  127. this.$u.toast("请输入验证码")
  128. return
  129. }
  130. let res = await this.$api.loginUser.h5Login(this.form)
  131. if (this.$isEmpty(res.data.data)) {
  132. this.$u.toast(res.data.msg)
  133. return
  134. }
  135. let userInfo = res.data.data
  136. console.log(userInfo);
  137. this.$u.toast("登录成功")
  138. this.$cache.put("userInfo", userInfo)
  139. this.$u.vuex('vuex_userId', userInfo.id)
  140. this.$u.vuex('vuex_phone', userInfo.phone)
  141. console.log(this.vuex_phone, "this.vuex_phone");
  142. this.$emit('signIn', userInfo)
  143. this.hide()
  144. },
  145. //获取手机号
  146. showPhoneModal() {
  147. this.phoneShow = true
  148. },
  149. //隐藏授权弹框
  150. hidePhoneModal() {
  151. this.phoneShow = false
  152. },
  153. show(notToast) {
  154. this.notToast = notToast || false
  155. //获取邀请码
  156. this.inviteCode = this.$cache.get('inviteCode')
  157. this.dialogShow = true
  158. // #ifdef MP-WEIXIN
  159. this.$mpi.wxLogin().then(res => {
  160. this.jscode = res.code
  161. })
  162. this.setTimer()
  163. // #endif
  164. },
  165. hide() {
  166. if (this.timer) {
  167. clearTimeout(this.timer)
  168. this.timer = null
  169. }
  170. this.dialogShow = false;
  171. this.$emit('hide')
  172. },
  173. async setTimer() {
  174. let respWx = await this.$mpi.wxLogin()
  175. this.jscode = respWx.code
  176. // 每隔4分钟重新请求 jscode
  177. this.timer = setTimeout(() => {
  178. this.setTimer()
  179. }, 240000)
  180. },
  181. getUserProfile(e) {
  182. uni.getUserProfile({
  183. desc: '用于获取头像和昵称',
  184. success: (res) => {
  185. this.userInfo = res.userInfo
  186. console.log("getUserProfile获取用户信息", this.userInfo);
  187. this.doLogin()
  188. }
  189. })
  190. },
  191. getuserinfo(e) {
  192. console.log("getuserinfo获取用户信息", e);
  193. if (e.detail.errMsg != 'getUserInfo:ok') {
  194. return
  195. }
  196. this.userInfo = e.detail.userInfo
  197. this.doLogin()
  198. },
  199. getSex(gender) {
  200. if (gender == 1) {
  201. return "男"
  202. } else if (gender == 2) {
  203. return "女"
  204. } else {
  205. return "保密"
  206. }
  207. },
  208. async doLogin() {
  209. this.dialogShow = false
  210. try {
  211. this.respLogin = (await this.$api.wxApp.getOpenId({
  212. code: this.jscode
  213. })).data
  214. let openId = this.respLogin.data.openid
  215. if (this.$isEmpty(openId)) {
  216. this.$refs.toast.error('登录失败')
  217. return
  218. }
  219. let unionid = this.respLogin.data.unionid || ''
  220. this.sessionKey = this.respLogin.data.session_key
  221. //通过openid查询数据库中该用户是否存在
  222. let params = {
  223. nickName: this.userInfo.nickName,
  224. avatar: this.userInfo.avatarUrl,
  225. sex: this.getSex(this.userInfo.gender),
  226. unionid,
  227. openid: openId,
  228. province: this.userInfo.province,
  229. city: this.userInfo.city
  230. }
  231. //将openid
  232. let resp = await this.$api.loginUser.login(params)
  233. let userData = resp.data.data
  234. if (this.$isNotEmpty(userData.id)) {
  235. //登录成功
  236. let obj = {
  237. ...userData,
  238. sessionKey: this.sessionKey,
  239. }
  240. //将openid和sessionkey存进缓存中,有效时间为七天
  241. this.$cache.put("userInfo", obj)
  242. this.$u.vuex('vuex_userId', userData.id)
  243. if (userData.phone) {
  244. this.$u.vuex('vuex_phone', userData.phone)
  245. }
  246. //移除邀请码
  247. this.$cache.remove('inviteCode')
  248. this.dialogShow = false
  249. //获取手机号
  250. if (this.$isEmpty(this.vuex_phone) && this.$config.isAuthPhone) {
  251. this.showPhoneModal()
  252. } else {
  253. if (!this.notToast) {
  254. this.$u.toast('登录成功')
  255. }
  256. }
  257. //登录成功
  258. this.$emit('signIn', resp)
  259. } else {
  260. this.$refs.toast.error('登录失败')
  261. }
  262. } catch (e) {
  263. console.error(e);
  264. this.$refs.toast.error('登录失败')
  265. } finally {
  266. if (this.timer) {
  267. clearTimeout(this.timer)
  268. this.setTimer()
  269. }
  270. }
  271. },
  272. clear() {
  273. return
  274. },
  275. async getphonenumber(e) {
  276. this.hidePhoneModal()
  277. if (e.detail.errMsg != 'getPhoneNumber:ok') {
  278. console.log("获取手机号失败");
  279. return
  280. }
  281. if (this.$isEmpty(this.sessionKey)) {
  282. this.sessionKey = this.$cache.get('userInfo').sessionKey
  283. }
  284. let params = {
  285. sessionKey: this.sessionKey,
  286. encryptedData: e.detail.encryptedData,
  287. iv: e.detail.iv
  288. }
  289. this.$api.wxApp.getOpenData(params).then(res => {
  290. if (res.data.success) {
  291. let obj = JSON.parse(res.data.data)
  292. let phone = obj.phoneNumber
  293. this.cachePhone(phone)
  294. }
  295. })
  296. },
  297. cachePhone(phone) {
  298. let userInfo = this.$cache.get('userInfo')
  299. let params = {
  300. userId: userInfo.id,
  301. phone
  302. }
  303. this.$api.loginUser.savePhone(params).then(res => {
  304. console.log(res);
  305. if (res.data.success) {
  306. userInfo.phone = phone
  307. this.$cache.put('userInfo', userInfo)
  308. this.$u.vuex('vuex_phone', phone)
  309. this.$emit('phoneSuccess')
  310. } else {
  311. this.$refs.toast.error(res.msg)
  312. }
  313. })
  314. }
  315. }
  316. };
  317. </script>
  318. <style lang="scss">
  319. .popup_mask {
  320. position: fixed;
  321. bottom: 0;
  322. top: 0;
  323. left: 0;
  324. right: 0;
  325. background-color: rgba(0, 0, 0, 0.4);
  326. opacity: 1;
  327. z-index: 98;
  328. }
  329. .dt-login-wrap {
  330. position: fixed;
  331. border-radius: 16rpx;
  332. background: #ffffff;
  333. width: 560rpx;
  334. z-index: 99;
  335. bottom: 30%;
  336. left: 50%;
  337. margin-left: -280rpx;
  338. right: 0;
  339. text-align: center;
  340. .title {
  341. padding-top: 40upx;
  342. font-size: 34upx;
  343. font-weight: bold;
  344. }
  345. .content {
  346. display: flex;
  347. justify-content: center;
  348. align-items: center;
  349. flex-direction: column;
  350. padding-top: 30rpx;
  351. padding-bottom: 150rpx;
  352. .userinfo-avatar {
  353. overflow: hidden;
  354. display: block;
  355. width: 140rpx;
  356. height: 140rpx;
  357. margin: 20rpx 20rpx 40rpx;
  358. border-radius: 50%;
  359. border: 2px solid #fff;
  360. }
  361. }
  362. .subtitle {
  363. color: #7e7e7e;
  364. font-size: 26upx;
  365. margin-top: 30rpx;
  366. }
  367. .btn-content {
  368. display: flex;
  369. width: 100%;
  370. border-radius: 0;
  371. border-top: 1upx solid #ebebeb;
  372. button {
  373. border: none;
  374. width: 50%;
  375. font-size: 30rpx;
  376. background-color: #FFFFFF;
  377. color: #66656a;
  378. }
  379. button:first-child {
  380. border-right: 1rpx solid #ebebeb;
  381. border-radius: 0 0 0 18rpx;
  382. }
  383. button:last-child {
  384. color: var(--bgColor);
  385. border-radius: 0 0 18rpx 0;
  386. }
  387. }
  388. .btn-content button::after {
  389. border: none;
  390. }
  391. }
  392. </style>