li.shaoyi 2 vuotta sitten
vanhempi
commit
62d37d682a

+ 41 - 47
src/business/login/index.ts

@@ -1,10 +1,8 @@
 import { reactive } from 'vue'
 import { v4 } from 'uuid'
-import { encryptAES, decryptAES } from '@/utils/crypto'
 import { timerTask } from '@/utils/timer'
 import { ClientType } from '@/constants/client'
 import { queryLoginId, login } from '@/services/api/account'
-import { sessionData, localData } from '@/stores/storage'
 import { useLoginStore, useEnumStore, useErrorInfoStore, useUserStore, useFuturesStore, useAccountStore } from '@/stores'
 import { checkToken, checkTokenLoop } from '@/business/common'
 import service from '@/services'
@@ -12,7 +10,12 @@ import socket from '@/services/socket'
 import eventBus from '@/services/bus'
 import cryptojs from 'crypto-js'
 
-export function useLogin() {
+/**
+ * 登录业务模块
+ * @param persist 登录状态是否持久化
+ * @returns 
+ */
+export function useLogin(persist = false) {
     const enumStore = useEnumStore()
     const errorInfoStore = useErrorInfoStore()
     const loginStore = useLoginStore()
@@ -48,49 +51,40 @@ export function useLogin() {
         checkTokenLoop()
     }
 
-    const loginAction = async (params: Proto.LoginReq) => {
-        params.GUID = v4()
-        await login(params).then((res) => {
-            const encryptedData = encryptAES(JSON.stringify(params)) // 数据加密
-            localData.setValue('autoLoginEncryptedData', encryptedData)
-            loginStore.$setState((state) => {
-                state.loginInfo = res
-            })
-            localStorage.setItem('thj_loginId', formData.LoginID) // 记住登录ID
-        })
-        await loadUserData()
-        eventBus.$emit('LoginNotify') // 登录成功通知
-    }
-
-    // 自动登录
-    const autoLogin = async () => {
-        try {
-            logining.value = true
-            const encryptedData = localData.getValue('autoLoginEncryptedData')
-            if (encryptedData) {
-                const decryptedString = decryptAES(encryptedData)
-                return await loginAction(JSON.parse(decryptedString))
-            }
-            return Promise.reject('自动登录失败')
-        } finally {
-            logining.value = false
-        }
-    }
-
     // 用户登录
-    const userLogin = async (clientType: ClientType) => {
-        logining.value = true
-        formData.ClientType = clientType
+    const userLogin = async (autoLogin = false) => {
         try {
-            const params = { ...formData }
+            logining.value = true
             await loadBaseData()
-            await queryLoginId({
-                username: formData.LoginID
-            }).then((res) => {
-                params.LoginID = res.data
-                params.LoginPWD = cryptojs.SHA256(res.data + formData.LoginPWD).toString()
+            const payload = await new Promise<Proto.LoginReq>((resolve, reject) => {
+                if (autoLogin) {
+                    const params = loginStore.getAutoLoginData()
+                    if (params) {
+                        resolve(params)
+                    } else {
+                        reject('自动登录失败')
+                    }
+                } else {
+                    queryLoginId({
+                        username: formData.LoginID
+                    }).then((res) => {
+                        const params = { ...formData }
+                        params.LoginID = res.data
+                        params.LoginPWD = cryptojs.SHA256(res.data + formData.LoginPWD).toString()
+                        resolve(params)
+                    }).catch((err) => {
+                        reject(err)
+                    })
+                }
+            })
+            payload.GUID = v4()
+            await login(payload).then(async (res) => {
+                loginStore.setLoginInfo(res, persist)
+                loginStore.setAutoLoginData(payload)
+                localStorage.setItem('thj_loginId', formData.LoginID) // 记住登录ID
+                await loadUserData()
+                eventBus.$emit('LoginNotify') // 登录成功通知
             })
-            return await loginAction(params)
         } finally {
             logining.value = false
         }
@@ -100,19 +94,20 @@ export function useLogin() {
     const userLogout = (callback?: () => void) => {
         socket.closeAll()
         timerTask.clearAll()
-        sessionData.reset('loginInfo', 'userRoutes')
+        loginStore.clearAutoLoginData()
+        loginStore.clearLoginInfo()
         callback && callback()
     }
 
     // 初始化业务数据
-    const initBaseData = async (enableAutoLogin = false) => {
+    const initBaseData = async (autoLogin = false) => {
         try {
             logining.value = true
             await loadBaseData()
             if (token.value) {
                 await loadUserData()
-            } else if (enableAutoLogin) {
-                await autoLogin().catch(() => Promise.resolve())
+            } else if (autoLogin && loginStore.getAutoLoginData()) {
+                await userLogin(true)
             }
         } finally {
             logining.value = false
@@ -123,7 +118,6 @@ export function useLogin() {
         logining,
         formData,
         initBaseData,
-        autoLogin,
         userLogin,
         userLogout,
     }

+ 1 - 1
src/packages/mobile/router/animateRouter.ts

@@ -9,7 +9,7 @@ interface HistoryState {
 }
 
 export default new (class {
-    private storageKey = 'mobile@' + window.location.hostname;
+    private storageKey = 'history_mobile';
 
     private _state = ref<HistoryState>({
         history: [],

+ 2 - 2
src/packages/mobile/views/boot/index.vue

@@ -63,11 +63,11 @@ const skip = (promise: Promise<void>) => {
     if (redirect) {
       router.replace(redirect.toString())
     } else {
-      router.replace({ name: 'home' })
+      router.replace({ name: 'home-index' })
     }
   }).catch((err) => {
     if (service.isReady) {
-      router.replace({ name: 'home' })
+      router.replace({ name: 'home-index' })
     } else {
       tryInit(err)
     }

+ 2 - 2
src/packages/mobile/views/home/index.vue

@@ -25,7 +25,7 @@ import AppTabbar from '@mobile/components/base/tabbar/index.vue'
 import RouterTransition from '@mobile/components/base/router-transition/index.vue'
 
 const { route, routerTo, getGlobalUrlParams } = useNavigation()
-const { autoLogin } = useLogin()
+const { userLogin } = useLogin()
 const loginStore = useLoginStore()
 const cssTransition = shallowRef(true) // 是否使用css动画
 const currentTab = shallowRef(0)
@@ -66,7 +66,7 @@ const onTabClick = (index: number) => {
     routerTo(name, true)
   } else {
     fullloading((hideLoading) => {
-      autoLogin().then(() => {
+      userLogin(true).then(() => {
         currentTab.value = index
         routerTo(name, true)
       }).catch(() => {

+ 2 - 2
src/packages/mobile/views/user/login/index.vue

@@ -79,8 +79,8 @@ const getClientType = () => {
 const formSubmit = () => {
   if (checked.value) {
     fullloading((hideLoading) => {
-      const clientType = getClientType()
-      userLogin(clientType).then(() => {
+      formData.ClientType = getClientType()
+      userLogin().then(() => {
         hideLoading()
         routerBack()
         showSuccessToast('登录成功')

+ 1 - 1
src/packages/pc/router/historyRouter.ts

@@ -16,7 +16,7 @@ interface HistoryState {
 }
 
 export default new (class {
-    private storageKey = 'pc@' + window.location.hostname;
+    private storageKey = 'history_pc';
 
     private _state = ref<HistoryState>({
         historyStacks: [],

+ 2 - 1
src/packages/pc/views/auth/login/index.vue

@@ -54,7 +54,8 @@ const formSubmit = () => {
     if (valid) {
       try {
         loading.value = true
-        await userLogin(ClientType.Web)
+        formData.ClientType = ClientType.Web
+        await userLogin()
         await menuStore.getUserMenuList()
         const redirect = route.query.redirect
         if (redirect) {

+ 3 - 7
src/services/http/index.ts

@@ -47,7 +47,7 @@ export default new (class {
             },
             (err) => {
                 if (err.message === 'Network Error') {
-                    return Promise.reject('无网络连接,请检查网络')
+                    return Promise.reject('无效的网络连接')
                 }
                 if (err.response) {
                     const { msg, message } = err.response.data ?? {}
@@ -93,9 +93,7 @@ export default new (class {
 
     /**
      * Http 请求
-     * @param url 
-     * @param method 
-     * @param payload 
+     * @param config 
      * @param errMsg 
      * @returns 
      */
@@ -116,9 +114,7 @@ export default new (class {
 
     /**
      * Http 通用请求
-     * @param url 
-     * @param method 
-     * @param payload 
+     * @param config 
      * @param errMsg 
      * @returns 
      */

+ 80 - 11
src/stores/modules/login.ts

@@ -1,41 +1,110 @@
-import { computed, ref } from 'vue'
+import { reactive, toRefs, computed } from 'vue'
+import { encryptAES, decryptAES } from '@/utils/crypto'
 import { defineStore } from '../store'
-import { sessionData } from '../storage'
+import { localData, sessionData } from '../storage'
+
+// 初始化登录信息
+function initLoginInfo(): Proto.LoginRsp {
+    return {
+        RetCode: 0,
+        RetDesc: '',
+        AccountIDs: [],
+        LoginCode: '',
+        LoginID: 0,
+        LoginUserType: 0,
+        AccountStatus: 0,
+        UserID: 0,
+        ClientID: 0,
+        MemberUserID: 0,
+        Token: '',
+    }
+}
 
 /**
  * 登录存储对象
  */
 export const useLoginStore = defineStore(() => {
-    const logining = ref(false)
-    const loginInfo = sessionData.getRef('loginInfo')
+    const localLoginInfo = localData.getValue('loginInfo')
+    const sessionLoginInfo = sessionData.getValue('loginInfo')
+
+    const state = reactive({
+        logining: false,
+        loginInfo: localLoginInfo || sessionLoginInfo || initLoginInfo()
+    })
 
     // 登录令牌
-    const token = computed(() => loginInfo.value.Token)
+    const token = computed(() => state.loginInfo.Token)
 
     // 用户ID
-    const userId = computed(() => loginInfo.value.UserID)
+    const userId = computed(() => state.loginInfo.UserID)
 
     // 登录ID
-    const loginId = computed(() => loginInfo.value.LoginID)
+    const loginId = computed(() => state.loginInfo.LoginID)
 
     // 首个资金账户ID
     const firstAccountId = computed(() => {
-        const accounts = loginInfo.value.AccountIDs
+        const accounts = state.loginInfo.AccountIDs
         return accounts[0] ?? 0
     })
 
     // 获取用户登录信息
     const getLoginInfo = <K extends keyof Proto.LoginRsp>(key: K) => {
-        return loginInfo.value[key]
+        return state.loginInfo[key]
+    }
+
+    // 更新登录信息
+    const setLoginInfo = (data: Proto.LoginRsp, persist = false) => {
+        state.loginInfo = data
+        if (persist) {
+            localData.setValue('loginInfo', data) // 缓存登录状态到本地
+            sessionData.reset('loginInfo')
+        } else {
+            sessionData.setValue('loginInfo', data) // 缓存登录状态到会话
+            localData.reset('loginInfo')
+        }
+    }
+
+    // 获取自动登录信息
+    const getAutoLoginData = () => {
+        try {
+            const encryptedData = localData.getValue('autoLoginEncryptedData')
+            const decryptedString = decryptAES(encryptedData)
+            return JSON.parse(decryptedString) as Proto.LoginReq
+        } catch (err) {
+            clearAutoLoginData()
+            return undefined
+        }
+    }
+
+    // 更新自动登录信息
+    const setAutoLoginData = (data: Proto.LoginReq) => {
+        const encryptedString = encryptAES(JSON.stringify(data)) // 数据加密
+        localData.setValue('autoLoginEncryptedData', encryptedString)
+    }
+
+    // 清除自动登录信息
+    const clearAutoLoginData = () => {
+        localData.reset('autoLoginEncryptedData')
+    }
+
+    // 清除登录信息
+    const clearLoginInfo = () => {
+        localData.reset('loginInfo')
+        sessionData.reset('loginInfo')
+        state.loginInfo = initLoginInfo()
     }
 
     return {
-        logining,
-        loginInfo,
+        ...toRefs(state),
         token,
         userId,
         loginId,
         firstAccountId,
         getLoginInfo,
+        setLoginInfo,
+        getAutoLoginData,
+        setAutoLoginData,
+        clearAutoLoginData,
+        clearLoginInfo,
     }
 })

+ 2 - 13
src/stores/storage.ts

@@ -6,25 +6,14 @@ function createLocalData() {
     return {
         appLanguage: Language.ZhCN,
         appTheme: AppTheme.Default,
+        loginInfo: <Proto.LoginRsp | undefined>undefined,
         autoLoginEncryptedData: '', // 自动登录加密数据
     }
 }
 
 function createSessionData() {
     return {
-        loginInfo: <Proto.LoginRsp>{
-            RetCode: 0,
-            RetDesc: '',
-            AccountIDs: [],
-            LoginCode: '',
-            LoginID: 0,
-            LoginUserType: 0,
-            AccountStatus: 0,
-            UserID: 0,
-            ClientID: 0,
-            MemberUserID: 0,
-            Token: '',
-        },
+        loginInfo: <Proto.LoginRsp | undefined>undefined,
         userRoutes: <Model.UserRoutes[]>[],
         allEnums: <Model.EnumRsp[]>[], // 枚举信息
         errorInfos: <Model.ErrorInfosRsp[]>[], // 错误信息

+ 2 - 2
src/utils/storage/index.ts

@@ -4,7 +4,7 @@ import { shallowRef, ShallowRef, watch } from 'vue'
  * 本地存储类
  */
 export default class <T extends object> {
-    constructor(storage: Storage, source: T, prefix = '@') {
+    constructor(storage: Storage, source: T, prefix = '') {
         this.prefix = prefix
         this.storage = storage
         this.source = source
@@ -29,7 +29,7 @@ export default class <T extends object> {
     private observe<K extends keyof T>(key: K) {
         watch(this.getRef(key), (value) => {
             if (value === undefined || value === null) {
-                this.reset(key)
+                this.storage.removeItem(this.prefix + key.toString())
             } else {
                 const strValue = JSON.stringify(value) // 注意数值长度过长会被自动转换为 String 类型
                 this.storage.setItem(this.prefix + key.toString(), strValue)