login.tsx 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. import { defineComponent } from 'vue'
  2. import { CellGroup, Field, Button, CountDown, Row, Col, showToast, Popup } from 'vant'
  3. import ImgCode from '@/components/o-img-code'
  4. import { checkPhone } from '@/helpers/validate'
  5. import { setLogin, state } from '@/state'
  6. import { removeAuth, setAuth } from './utils'
  7. import styles from './index.module.less'
  8. import request from '@/helpers/request'
  9. import { browser, getUrlCode } from '@/helpers/utils'
  10. import qs from 'query-string'
  11. type loginType = 'PWD' | 'SMS'
  12. export default defineComponent({
  13. name: 'login-music',
  14. data() {
  15. return {
  16. loginType: 'SMS' as loginType,
  17. username: '',
  18. password: '',
  19. smsCode: '',
  20. countDownStatus: true, // 是否发送验证码
  21. countDownTime: 1000 * 120, // 倒计时时间
  22. // countDownRef: null as any, // 倒计时实例
  23. imgCodeStatus: false,
  24. showPopup: false,
  25. code: '' // 授权code码
  26. }
  27. },
  28. computed: {
  29. codeDisable() {
  30. let status = true
  31. this.username && this.smsCode && (status = false)
  32. return status
  33. }
  34. },
  35. mounted() {
  36. removeAuth()
  37. this.directNext()
  38. // 判断是否是微信,只能微信中打开
  39. if (browser().weixin) {
  40. // 微信公众号支付
  41. //授权
  42. const code = getUrlCode()
  43. console.log('login mounted code: ' + code)
  44. if (!code) {
  45. this.getAppIdAndCode()
  46. } else {
  47. this.code = code
  48. }
  49. } else {
  50. this.showPopup = true
  51. }
  52. },
  53. methods: {
  54. async getAppIdAndCode() {
  55. try {
  56. const { data } = await request.get('/api-student/open/paramConfig/wechatAppId')
  57. // 判断是否有微信appId
  58. if (data) {
  59. this.goAuth(data)
  60. }
  61. } catch {
  62. //
  63. }
  64. },
  65. goAuth(wxAppId: string) {
  66. // 用户授权
  67. const urlNow = encodeURIComponent(window.location.href)
  68. const scope = 'snsapi_base' //snsapi_userinfo //静默授权 用户无感知
  69. const appid = wxAppId || 'wx8654c671631cfade'
  70. const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${urlNow}&response_type=code&scope=${scope}&state=STATE&connect_redirect=1#wechat_redirect`
  71. window.location.replace(url)
  72. },
  73. directNext() {
  74. if (state.user.status === 'login' || state.user.status === 'error') {
  75. const { returnUrl, isRegister, ...rest } = this.$route.query
  76. console.log(
  77. {
  78. ...rest,
  79. code: this.code
  80. },
  81. 'jump pre registration'
  82. )
  83. // console.log(returnUrl, isRegister, { ...rest })
  84. // this.$router.replace({
  85. // path: returnUrl as any,
  86. // query: {
  87. // ...rest,
  88. // code: this.code
  89. // }
  90. // })
  91. const newUrl =
  92. window.location.origin +
  93. window.location.pathname +
  94. '#' +
  95. returnUrl +
  96. '?' +
  97. qs.stringify({
  98. ...rest,
  99. code: this.code
  100. })
  101. this.locationReplace(newUrl)
  102. }
  103. },
  104. locationReplace(url: any) {
  105. // 只允许同域名
  106. console.log(history.replaceState, 'window.history.replaceState')
  107. if (history.replaceState) {
  108. history.replaceState(null, document.title, url)
  109. history.go(0)
  110. } else {
  111. location.replace(url)
  112. }
  113. },
  114. async onLogin() {
  115. try {
  116. // let res: any
  117. const forms: any = {
  118. username: this.username,
  119. client_id: 'jmedu-student',
  120. client_secret: 'jmedu-student',
  121. autoRegister: true,
  122. password: this.smsCode,
  123. loginType: 'SMS',
  124. grant_type: 'SMS'
  125. }
  126. const { data } = await request.post('/api-oauth/userlogin', {
  127. requestType: 'form',
  128. data: {
  129. ...forms
  130. }
  131. })
  132. setAuth(data.token_type + ' ' + data.access_token)
  133. const userCash = await request.get('/api-student/appLoginUser/getUserInfo', {
  134. initRequest: true // 初始化接口
  135. })
  136. setLogin(userCash.data)
  137. this.directNext()
  138. } catch {
  139. //
  140. }
  141. },
  142. async onSendCode() {
  143. // 发送验证码
  144. if (!checkPhone(this.username)) {
  145. return showToast('请输入正确的手机号码')
  146. }
  147. this.imgCodeStatus = true
  148. },
  149. onCodeSend() {
  150. this.countDownStatus = false
  151. this.$nextTick(() => {
  152. ;(this.$refs.countDownRef as any).start()
  153. })
  154. },
  155. onFinished() {
  156. this.countDownStatus = true
  157. ;(this.$refs.countDownRef as any).reset()
  158. },
  159. onChange() {
  160. if (this.loginType === 'PWD') {
  161. this.loginType = 'SMS'
  162. } else if (this.loginType === 'SMS') {
  163. this.loginType = 'PWD'
  164. }
  165. }
  166. },
  167. render() {
  168. return (
  169. <div class={styles.login}>
  170. <div class={styles.loginTitle}>
  171. 您好,
  172. <br /> 欢迎使用管乐团学生端
  173. </div>
  174. <CellGroup class={styles.margin34} border={false}>
  175. <Row style={{ marginBottom: '16px' }}>
  176. <Col span={24} class={styles.formTitle}>
  177. 手机号
  178. </Col>
  179. <Col span={24} class="van-hairline--bottom">
  180. <Field
  181. v-model={this.username}
  182. name="手机号"
  183. placeholder="请输入您的手机号"
  184. type="tel"
  185. maxlength={11}
  186. />
  187. </Col>
  188. </Row>
  189. <Row>
  190. <Col span={24} class={styles.formTitle}>
  191. 验证码
  192. </Col>
  193. <Col span={24} class="van-hairline--bottom">
  194. <Field
  195. v-model={this.smsCode}
  196. name="验证码"
  197. placeholder="请输入验证码"
  198. type="tel"
  199. maxlength={6}
  200. v-slots={{
  201. button: () =>
  202. this.countDownStatus ? (
  203. <span class={styles.codeText} onClick={this.onSendCode}>
  204. 获取验证码
  205. </span>
  206. ) : (
  207. <CountDown
  208. ref="countDownRef"
  209. auto-start={false}
  210. time={this.countDownTime}
  211. onFinish={this.onFinished}
  212. format="ss秒"
  213. />
  214. )
  215. }}
  216. />
  217. </Col>
  218. </Row>
  219. </CellGroup>
  220. <div class={styles.margin34}>
  221. <Button round block type="primary" disabled={this.codeDisable} onClick={this.onLogin}>
  222. 提交
  223. </Button>
  224. </div>
  225. {this.imgCodeStatus ? (
  226. <ImgCode
  227. v-model:value={this.imgCodeStatus}
  228. phone={this.username}
  229. onClose={() => {
  230. this.imgCodeStatus = false
  231. }}
  232. onSendCode={this.onCodeSend}
  233. />
  234. ) : null}
  235. <Popup
  236. v-model:show={this.showPopup}
  237. round
  238. style={{ width: '92%' }}
  239. closeOnClickOverlay={false}
  240. >
  241. <div class={styles.popupContainer}>
  242. <div class={styles.dialogTitle}>
  243. <i></i>
  244. 提示
  245. </div>
  246. <p class={styles.popupTips}>请使用微信打开</p>
  247. </div>
  248. </Popup>
  249. </div>
  250. )
  251. }
  252. })