index.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <route lang="json5" type="page">
  2. {
  3. style: {
  4. navigationBarTitleText: '登录',
  5. },
  6. }
  7. </route>
  8. <template>
  9. <wd-toast></wd-toast>
  10. <view class="login">
  11. <view class="login-main">
  12. <text class="login-main-title">欢迎登录</text>
  13. <view class="login-main-subtitle">使用猫耳云打印小程序</view>
  14. <view class="login-main-body">
  15. <!-- <login-input key="username" v-model="username" clearable placeholder="用户名" :maxlength="20"></login-input>
  16. <view class="login-password">
  17. <login-input key="password" v-model="password" password clearable placeholder="密码" :maxlength="20"></login-input>
  18. </view> -->
  19. <wd-button v-if="isLogout && !token" size="large" block type="primary" @click="init()">快捷登录</wd-button>
  20. <wd-button v-if="token" size="large" block type="primary" open-type="getPhoneNumber" :phone-number-no-quota-toast="false" @getphonenumber="onGetPhoneNumber">手机号授权</wd-button>
  21. </view>
  22. </view>
  23. <view class="login-footer">
  24. <text>广东省中宝奥科技有限公司</text>
  25. </view>
  26. </view>
  27. </template>
  28. <script lang="ts" setup>
  29. import { useToast } from 'wot-design-uni'
  30. import { useUserStore } from '@/store'
  31. import { loginByCode, bingPhoneByCode } from '@/service/api/index'
  32. import { getLoginCode } from '@/utils'
  33. // import LoginInput from './components/LoginInput.vue'
  34. const toast = useToast()
  35. const isLogout = ref(false)
  36. const username = ref<string>('') // 用户名
  37. const password = ref<string>('') // 密码
  38. const token = ref<string>('') // 令牌
  39. const qrToken = ref<string>('') // web端扫小程序码 登录带入的令牌
  40. async function init() {
  41. token.value = ""
  42. const code = await getLoginCode()
  43. let params = {
  44. code,
  45. qrToken: qrToken.value
  46. }
  47. loginByCode(params).then((res) => {
  48. if (res.code == 0 ) {
  49. switch (res.body.res) {
  50. case "0":
  51. handleToken(res.body.token || "")
  52. break;
  53. case "1":
  54. token.value = res.body.token || ""
  55. toast.warning("请进行手机号授权")
  56. break;
  57. default:
  58. toast.error({ msg: '获取token异常', duration: 4000 })
  59. break;
  60. }
  61. } else {
  62. toast.error({ msg: '获取token异常', duration: 4000 })
  63. }
  64. }).catch((error) => {
  65. toast.close()
  66. toast.error({ msg: error!.data!.message || '获取token异常', duration: 4000 })
  67. })
  68. }
  69. function handleToken(token) {
  70. if (token) {
  71. useUserStore().setToken(token)
  72. // useUserStore().initUserInfo()
  73. uni.reLaunch({
  74. url: `/pages/index/index`,
  75. })
  76. } else {
  77. handleTokenError()
  78. }
  79. }
  80. function handleTokenError() {
  81. toast.error({ msg: '登录失败, 请重新登录', duration: 4000 })
  82. init()
  83. }
  84. /**
  85. * 手机号实时验证组件: 获取并验证手机号
  86. * e.detail.code -- 动态令牌; e.detail.errMsg --- 回调信息(成功失败都会返回); e.detail.errno -- 错误码(失败时返回)
  87. */
  88. function onGetPhoneNumber(detail) {
  89. if(detail.errMsg == "getPhoneNumber:ok" && detail.code) {
  90. handlePhoneNumberLogin(detail.code)
  91. } else {
  92. let tips = ""
  93. if (detail.errno === 1400001) {
  94. tips = "验证失败,请使用验证码方式"
  95. } else if (detail.errMsg.includes('user deny') || detail.errMsg.includes('user cancel')) {
  96. tips = "验证取消,请重新选择手机号"
  97. } else if (detail.errMsg.includes('freq limit')) {
  98. tips = "频率受限,请稍后重试"
  99. } else {
  100. tips = "验证失败,请稍后重试"
  101. }
  102. uni.showToast({
  103. title: tips,
  104. icon: "none",
  105. duration: 2000
  106. })
  107. }
  108. }
  109. // 根据code换取手机号, 进行绑定 (必须绑定)
  110. function handlePhoneNumberLogin(code) {
  111. let params = {
  112. code,
  113. token: token.value || '',
  114. qrToken: qrToken.value || '',
  115. }
  116. bingPhoneByCode(params).then((res) => {
  117. if (res.code == 0 && res.body.res == 0) {
  118. handleToken(res.body.token)
  119. } else {
  120. handleTokenError()
  121. }
  122. }).catch((error) => {
  123. toast.error({ msg: error!.data!.message || '登录失败, 请重新登录', duration: 4000 })
  124. })
  125. }
  126. onLoad((option: any) => {
  127. isLogout.value = option.isLogout == "1"
  128. qrToken.value = option.scene || ""
  129. if(!isLogout.value) init()
  130. })
  131. </script>
  132. <style lang="scss" scoped>
  133. .login {
  134. background-color: #ffffff;
  135. height: calc(100vh - var(--window-top));
  136. width: 100vw;
  137. box-sizing: border-box;
  138. &-main {
  139. padding: 112rpx 75rpx 0 75rpx;
  140. position: relative;
  141. &-title {
  142. display: flex;
  143. justify-content: center;
  144. align-items: center;
  145. height: 64rpx;
  146. font-size: 48rpx;
  147. font-weight: 600;
  148. line-height: 64rpx;
  149. letter-spacing: 8rpx;
  150. }
  151. &-subtitle {
  152. font-size: 28rpx;
  153. line-height: 40rpx;
  154. letter-spacing: 12rpx;
  155. text-align: center;
  156. margin: 8rpx 0 104rpx;
  157. }
  158. &-body {
  159. position: relative;
  160. box-sizing: border-box;
  161. width: 600rpx;
  162. height: 70vh;
  163. // 仅用于 显示账号密码登录时
  164. // .login-password {
  165. // position: relative;
  166. // padding: 40rpx 0 104rpx;
  167. // }
  168. padding-top: 20vh;
  169. }
  170. }
  171. &-footer {
  172. display: flex;
  173. flex-direction: column;
  174. width: 100%;
  175. text-align: center;
  176. line-height: 28rpx;
  177. font-size: 24rpx;
  178. font-weight: 500;
  179. }
  180. }
  181. </style>