login.tsx 7.9 KB

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