login.uvue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. <template>
  2. <cl-page>
  3. <Back />
  4. <!-- <cl-image src="https://oss.xiaoxiongcode.com/static/home/1.jpg" mode="heightFix" class="w-full h-full object-cover"
  5. height="100%" width="100%" /> -->
  6. <view class="content">
  7. <view class="title">
  8. <cl-image src="https://oss.xiaoxiongcode.com/static/home/logo.png" width="120px" height="120px"
  9. mode="heightFix" />
  10. <cl-text :size="20" color="#666">
  11. 少儿物理启蒙
  12. </cl-text>
  13. </view>
  14. <view class="group">
  15. <view class="w-[80vw]">
  16. <!-- <cl-tabs v-model="val" :list="list" fill :form="formData" @change="tabsChange"></cl-tabs> -->
  17. <cl-form v-model="formData" :pt="{ className: 'mt-1' }">
  18. <view v-if="val === 'quickly_login'">
  19. <phone :form="formData" />
  20. </view>
  21. <view v-else-if="val === 'password'">
  22. <password :form="formData" />
  23. </view>
  24. <view class="flex flex-row items-center justify-center mb-5">
  25. <cl-button v-if="val === 'weixin'"
  26. :pt="{ className: '!h-[45px] !rounded-full w-[200px] mx-auto' }" type="success"
  27. @tap="toWechatLogin">
  28. <view class="flex flex-row items-center justify-center">
  29. <cl-image src="https://oss.xiaoxiongcode.com/static/个人中心/微信.png" mode="heightFix"
  30. height="20px" width="auto"></cl-image>
  31. <view class="ml-2">
  32. 微信快捷登录
  33. </view>
  34. </view>
  35. </cl-button>
  36. <cl-button v-else :disabled="!agree || !agree2"
  37. :pt="{ className: '!h-[45px] !rounded-full w-[200px] mx-auto' }" :loading="loading"
  38. @tap="toLogin">
  39. 登录
  40. </cl-button>
  41. </view>
  42. <cl-checkbox v-model="agree" v-if="val !== 'weixin'">
  43. <view class="flex flex-row items-center w-full text-[12px]">
  44. 同意并阅读
  45. <cl-text :size="12" color="primary" @tap.stop="toAgreement">
  46. 《用户服务协议》
  47. </cl-text>
  48. </view>
  49. </cl-checkbox>
  50. <cl-checkbox v-model="agree2" v-if="val !== 'weixin'">
  51. <view class="flex flex-row items-center w-full text-[12px]">
  52. 同意并阅读
  53. <cl-text :size="12" color="primary" @tap.stop="toPrivacy">
  54. 《隐私政策》
  55. </cl-text>
  56. </view>
  57. </cl-checkbox>
  58. </cl-form>
  59. </view>
  60. </view>
  61. <view class="absolute bottom-20 w-full flex flex-row gap-4 items-center justify-center">
  62. <view v-if="val !== 'weixin'">
  63. <cl-button type="success" :pt="{ className: '!h-[40px] !rounded-full w-[40px] mx-auto !p-1' }"
  64. :loading="loading" @tap="tabsChange('weixin')">
  65. <cl-image src="https://oss.xiaoxiongcode.com/static/个人中心/微信.png" mode="heightFix" height="20px"
  66. width="auto"></cl-image>
  67. </cl-button>
  68. <view class="mt-1">
  69. <cl-text :size="14" color="#666">
  70. 微信登录
  71. </cl-text>
  72. </view>
  73. </view>
  74. <view v-if="val !== 'quickly_login'">
  75. <cl-button type="info" :pt="{ className: '!h-[40px] !rounded-full w-[40px] mx-auto !p-1' }"
  76. :loading="loading" @tap="tabsChange('quickly_login')">
  77. <cl-image src="https://oss.xiaoxiongcode.com/static/home/phone.svg" mode="heightFix"
  78. height="20px" width="auto"></cl-image>
  79. </cl-button>
  80. <view class="mt-1">
  81. <cl-text :size="14" color="#666">
  82. 验证码登录
  83. </cl-text>
  84. </view>
  85. </view>
  86. <view v-if="val !== 'password'">
  87. <cl-button type="info" :pt="{ className: '!h-[40px] !rounded-full w-[40px] mx-auto !p-1' }"
  88. :loading="loading" @tap="tabsChange('password')">
  89. <cl-image src="https://oss.xiaoxiongcode.com/static/home/password.svg" mode="heightFix"
  90. height="20px" width="auto"></cl-image>
  91. </cl-button>
  92. <view class="mt-1">
  93. <cl-text :size="14" color="#666">
  94. 密码登录
  95. </cl-text>
  96. </view>
  97. </view>
  98. </view>
  99. </view>
  100. <cl-action-sheet ref="actionSheetRef">
  101. <template #prepend>
  102. <view class=" mb-3 font-bold text-center">
  103. <cl-text :size="20" color="#666">
  104. 选择登录账号
  105. </cl-text>
  106. </view>
  107. </template>
  108. </cl-action-sheet>
  109. <cl-popup v-model="visible" showClose :show-header="false" direction="center" :pt="{
  110. inner: {
  111. className: '!bg-transparent'
  112. }
  113. }">
  114. <view class="w-[330px] relative">
  115. <image src="https://oss.xiaoxiongcode.com/static/home/6172.png" mode="widthFix"
  116. class="w-[330px] relative ">
  117. </image>
  118. <view class=" wz-1 ">
  119. 当前微信账号,<br />尚未绑定,<br />无法快捷登录
  120. </view>
  121. <view class="wz-2 " @tap="handleClosePopup">
  122. 手机登录
  123. </view>
  124. </view>
  125. </cl-popup>
  126. </cl-page>
  127. </template>
  128. <script lang="ts" setup>
  129. import Back from '@/components/back.uvue'
  130. import type { LoginForm } from "./components/types";
  131. import phone from './components/phone.uvue';
  132. import password from './components/password.uvue';
  133. import { ref } from 'vue'
  134. import type { ClTabsItem } from "@/uni_modules/cool-ui";
  135. import { encryptPassword, user, router } from '@/.cool';
  136. import { loginApi, wechatLogin, quicklyRegister } from "@/services/user";
  137. import type { ClActionSheetOptions } from "@/uni_modules/cool-ui";
  138. const actionSheetRef = ref<ClActionSheetComponentPublicInstance | null>(null);
  139. const visible = ref(false)
  140. const val = ref('weixin')
  141. const agree = ref(false)
  142. const agree2 = ref(false)
  143. const list: ClTabsItem[] = [
  144. {
  145. label: '验证码登录',
  146. value: 'quickly_login'
  147. },
  148. {
  149. label: '密码登录',
  150. value: 'password'
  151. },
  152. {
  153. label: '微信登录',
  154. value: 'weixin'
  155. },
  156. ]
  157. const formData = ref<LoginForm>({
  158. username: '',
  159. password: '',
  160. randomStr: 0,
  161. grant_type: 'quickly_login',
  162. scope: 'server',
  163. loginType: 99,
  164. code: ''
  165. })
  166. const loading = ref(false)
  167. function tabsChange(type: string) {
  168. val.value = type
  169. if (val.value === 'quickly_login') {
  170. formData.value.code = ''
  171. formData.value.loginType = 99
  172. formData.value.grant_type = 'quickly_login'
  173. formData.value.password = ''
  174. } else {
  175. formData.value.grant_type = 'password'
  176. formData.value.password = ''
  177. formData.value.loginType = 1
  178. formData.value.code = ''
  179. }
  180. }
  181. function toLogin() {
  182. // loading.value = true
  183. console.log(formData.value);
  184. loginApi({
  185. ...formData.value,
  186. password: formData.value.password && encryptPassword(formData.value.password),
  187. }).then(res => {
  188. user.setToken(res)
  189. uni.showToast({
  190. title: '登录成功',
  191. icon: 'success'
  192. })
  193. router.home();
  194. }).catch(err => {
  195. if (err.message == '手机号不存在' && val.value === 'quickly_login') {
  196. quicklyRegister({
  197. username: formData.value.username,
  198. password: 'ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413',
  199. }).then(res => {
  200. handleSelect(formData.value.username)
  201. })
  202. } else {
  203. uni.showToast({
  204. title: err.message,
  205. icon: 'none'
  206. })
  207. }
  208. })
  209. }
  210. function handleClosePopup() {
  211. visible.value = false
  212. tabsChange('quickly_login')
  213. }
  214. function toWechatLogin() {
  215. uni.login({
  216. provider: 'weixin',
  217. success(res) {
  218. wechatLogin({
  219. code: res.code,
  220. }).then(res => {
  221. console.log(res);
  222. if (res.length === 0) {
  223. visible.value = true
  224. return
  225. } else if (res.length === 1) {
  226. handleSelect(res[0])
  227. return
  228. }
  229. const list = res.map(item => ({
  230. label: item,
  231. icon: "user-line",
  232. callback() {
  233. handleSelect(item)
  234. }
  235. }))
  236. actionSheetRef.value!.open({
  237. list: list
  238. } as ClActionSheetOptions);
  239. })
  240. }
  241. })
  242. }
  243. function handleSelect(item: string) {
  244. formData.value.username = item
  245. formData.value.password = 'quickly_login'
  246. formData.value.grant_type = 'quickly_login'
  247. formData.value.loginType = 88
  248. loginApi({
  249. ...formData.value,
  250. }).then(res => {
  251. user.setToken(res)
  252. uni.showToast({
  253. title: '登录成功',
  254. icon: 'success'
  255. })
  256. router.home();
  257. })
  258. }
  259. function toAgreement() {
  260. router.push({
  261. path: '/pages/user/agreement'
  262. })
  263. }
  264. function toPrivacy() {
  265. router.push({
  266. path: '/pages/user/privacy'
  267. })
  268. }
  269. </script>
  270. <style lang="scss" scoped>
  271. .content {
  272. @apply w-full h-full;
  273. // 渐变背景
  274. background: linear-gradient(180deg, #169deb5e 0%, #fff 20%);
  275. }
  276. .wz-1 {
  277. @apply absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-black text-3xl font-bold w-[300px] text-center;
  278. line-height: 40px;
  279. }
  280. .wz-2 {
  281. @apply absolute bottom-[12px] text-black text-2xl font-bold text-center;
  282. line-height: 40px;
  283. left: 50%;
  284. transform: translateX(-50%);
  285. }
  286. .title {
  287. position: absolute;
  288. top: 10%;
  289. //设置字间距
  290. letter-spacing: 0.1em;
  291. @apply flex flex-col w-full items-center justify-center;
  292. }
  293. .group {
  294. @apply absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white px-4 py-2 pb-10 rounded-xl;
  295. display: flex;
  296. align-items: center;
  297. flex-direction: row;
  298. }
  299. </style>