index.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import { shallowRef, reactive } from 'vue'
  2. import { v4 } from 'uuid'
  3. import { timerTask } from '@/utils/timer'
  4. import { wsLogin, httpLogin, queryLoginId } from '@/services/api/account'
  5. import { useGlobalStore, useLoginStore, useEnumStore, useErrorInfoStore, useUserStore, useFuturesStore, useAccountStore } from '@/stores'
  6. import service from '@/services'
  7. import quoteSocket from '@/services/websocket/quote'
  8. import tradeSocket from '@/services/websocket/trade'
  9. import tradeV2Socket from '@/services/websocket/tradeV2'
  10. import { encryptBody } from '@/services/websocket/package/crypto'
  11. import { checkToken, checkTokenLoop, stopCheckToken } from '@/business/common'
  12. import eventBus from '@/services/bus'
  13. import cryptojs from 'crypto-js'
  14. /**
  15. * 登录业务模块
  16. * @param persist 登录状态是否持久化---------不太合理的方式,待优化
  17. * @returns
  18. */
  19. export function useLogin(persist = false) {
  20. const globalStore = useGlobalStore()
  21. const enumStore = useEnumStore()
  22. const errorInfoStore = useErrorInfoStore()
  23. const loginStore = useLoginStore()
  24. const userStore = useUserStore()
  25. const accountStore = useAccountStore()
  26. const futuresStore = useFuturesStore()
  27. const { logining, token } = loginStore.$toRefs()
  28. const remember = shallowRef(true) // 记住账号
  29. const formData = reactive<Model.LoginReq>({
  30. userName: localStorage.getItem('app_loginId') ?? '',
  31. password: '',
  32. clientType: 0,
  33. })
  34. const loadBaseData = async () => {
  35. await service.onReady() // 等待服务初始化
  36. await Promise.all([
  37. errorInfoStore.getErrorInfoList(),
  38. enumStore.getAllEnumList(),
  39. ])
  40. }
  41. const loadUserData = async () => {
  42. await checkToken() // 令牌校验
  43. await Promise.all([
  44. userStore.getUserData(),
  45. accountStore.getAccountList(),
  46. ])
  47. futuresStore.getGoodsList()
  48. checkTokenLoop()
  49. if (globalStore.getSystemInfo('tradeChannel') === 'http') {
  50. tradeV2Socket.connect()
  51. }
  52. }
  53. // 用户登录
  54. const userLogin = async (autoLogin = false) => {
  55. try {
  56. logining.value = true
  57. await loadBaseData()
  58. const payload = await new Promise<Model.LoginReq>((resolve, reject) => {
  59. if (autoLogin) {
  60. const params = loginStore.getAutoLoginData()
  61. if (params) {
  62. resolve(params)
  63. } else {
  64. reject('自动登录失败')
  65. }
  66. } else {
  67. if (globalStore.getSystemInfo('tradeChannel') === 'ws') {
  68. // websocket 登录参数
  69. queryLoginId({
  70. data: {
  71. username: formData.userName
  72. }
  73. }).then((res) => {
  74. resolve({
  75. userName: res.data,
  76. password: cryptojs.SHA256(res.data + formData.password).toString(),
  77. clientType: loginStore.getClientType()
  78. })
  79. }).catch((err) => {
  80. reject(err)
  81. })
  82. } else {
  83. // http 登录参数
  84. resolve({
  85. userName: formData.userName,
  86. password: encryptBody(formData.password),
  87. clientType: loginStore.getClientType()
  88. })
  89. }
  90. }
  91. })
  92. if (globalStore.getSystemInfo('tradeChannel') === 'ws') {
  93. // websocket 登录
  94. const res = await wsLogin({
  95. LoginID: payload.userName,
  96. LoginPWD: payload.password,
  97. GUID: v4(),
  98. LoginType: 0,
  99. ClientType: payload.clientType,
  100. Version: '2.0.0.1',
  101. DeviceID: ''
  102. })
  103. // 更新登录信息
  104. loginStore.setLoginInfo({
  105. expiresAt: 0,
  106. loginId: res.LoginID,
  107. token: res.Token,
  108. userId: res.UserID,
  109. }, persist)
  110. } else {
  111. // http 登录
  112. const res = await httpLogin({ data: payload })
  113. // 更新登录信息
  114. loginStore.setLoginInfo(res.data, persist)
  115. }
  116. loginStore.setAutoLoginData(payload) // 更新自动登录信息
  117. localStorage.setItem('app_loginId', formData.userName) // 记住登录ID
  118. await loadUserData()
  119. eventBus.$emit('LoginNotify') // 登录成功通知
  120. } catch (err) {
  121. // 登录失败断开所有链路
  122. stopCheckToken()
  123. tradeSocket.close()
  124. tradeV2Socket.close()
  125. quoteSocket.close()
  126. timerTask.clearAll()
  127. return Promise.reject(err)
  128. } finally {
  129. logining.value = false
  130. }
  131. }
  132. // 用户登出
  133. const userLogout = (callback?: () => void) => {
  134. stopCheckToken()
  135. tradeSocket.close()
  136. tradeV2Socket.close()
  137. quoteSocket.close()
  138. timerTask.clearAll()
  139. userStore.$reset() // 待处理,重置后可能会出现多个重复的 store 实例
  140. accountStore.$reset() // 待处理,重置后可能会出现多个重复的 store 实例
  141. loginStore.clearAutoLoginData()
  142. loginStore.clearLoginInfo()
  143. callback && callback()
  144. }
  145. // 初始化业务数据
  146. const initBaseData = async (autoLogin = false) => {
  147. try {
  148. logining.value = true
  149. await loadBaseData()
  150. if (token.value) {
  151. await loadUserData()
  152. eventBus.$emit('LoginNotify') // 登录成功通知
  153. } else if (autoLogin && loginStore.getAutoLoginData()) {
  154. await userLogin(true)
  155. }
  156. } finally {
  157. logining.value = false
  158. }
  159. }
  160. return {
  161. logining,
  162. remember,
  163. formData,
  164. initBaseData,
  165. userLogin,
  166. userLogout,
  167. }
  168. }