Browse Source

[Feat 0000] 自动登录功能对接

houzekong 8 months ago
parent
commit
6b27ff3aa1

+ 48 - 0
src/hooks/vent/useAutoLogin.ts

@@ -0,0 +1,48 @@
+// 本来应该是后端做,出于工期考虑转到前端
+
+import QueryString from 'qs';
+import { useUserStore } from '/@/store/modules/user';
+import { RouteLocationNormalized } from 'vue-router';
+import { useMessage } from '../web/useMessage';
+
+/** 自动登录功能的Hook,该Hook是为了部署在同一局域网内的多套系统之间能够无缝切换 */
+export function useAutoLogin() {
+  /** 启用自动登录功能来跳转新的页面 */
+  function open(url: string, redirect?: string, target?: string) {
+    const userStore = useUserStore();
+    const qs = QueryString.stringify({
+      autoLogin: true,
+      username: userStore.getUserInfo.username,
+      workNo: userStore.getUserInfo.workNo,
+      redirect,
+    });
+    window.open(`${url}?${qs}`, target);
+  }
+
+  /** 用在路由守卫里,执行自动登录的逻辑,如果存在符合自动登录标准的query则执行自动登录 */
+  async function doAutoLogin(route: RouteLocationNormalized) {
+    const userStore = useUserStore();
+    if (!route.query) return;
+    const { autoLogin, username, workNo } = route.query;
+    if (!autoLogin || !username || !workNo) return;
+    const params = {
+      username: username as string,
+      workNo: workNo as string,
+      checkKey: new Date().getTime(),
+    };
+    try {
+      await userStore.autoLogin(params);
+    } catch (e: any) {
+      const message = useMessage().createMessage;
+      message.error(e.message);
+      return;
+    }
+  }
+
+  return {
+    /** 启用单点登录功能来跳转新的页面,参数与window.open一致,但需要注意url需要指向登录页 */
+    open,
+    /** 用在跳转到的页面上,执行单点登录的逻辑 */
+    doAutoLogin,
+  };
+}

+ 0 - 48
src/hooks/vent/useSSO.ts

@@ -1,48 +0,0 @@
-// 本来应该是后端做,出于工期考虑转到前端
-
-import QueryString from 'qs';
-import { useUserStore } from '/@/store/modules/user';
-import { useRoute, useRouter } from 'vue-router';
-
-/** 单点登录功能的Hook,该Hook是为了部署在同一局域网内的多套系统之间能够无缝切换 */
-export function useSSO() {
-  const router = useRouter();
-  const userStore = useUserStore();
-  const route = useRoute();
-
-  /** 启用单点登录功能来跳转新的页面 */
-  function open(url: string, redirect?: string, target?: string) {
-    const qs = QueryString.stringify({
-      username: userStore.userInfo?.username,
-      // 毫无意义的伪装,但我就是要装一下
-      id: userStore.getPassword,
-      redirect,
-    });
-    window.open(`${url}?${qs}`, target);
-  }
-
-  /** 用在跳转到的页面上,执行单点登录的逻辑 */
-  function doSSO() {
-    if (!route.query) return;
-    const { username, id, redirect } = route.query;
-    if (!username || !id) return;
-    const realPassword = userStore.decryptPassword(id as string);
-    const params = {
-      username: username as string,
-      password: realPassword,
-      checkKey: new Date().getTime(),
-    };
-    userStore.login(params).then(() => {
-      if (redirect) {
-        router.push(redirect as string);
-      }
-    });
-  }
-
-  return {
-    /** 启用单点登录功能来跳转新的页面,参数与window.open一致,但需要注意url需要指向登录页 */
-    open,
-    /** 用在跳转到的页面上,执行单点登录的逻辑 */
-    doSSO,
-  };
-}

+ 4 - 0
src/router/guard/permissionGuard.ts

@@ -17,6 +17,7 @@ import { useGlobSetting } from '/@/hooks/setting';
 import _ from 'lodash';
 import { AUTO_LOGIN_URL_QUERY, SKIP_SSO_URL_QUERY } from '../constant';
 import { useSso } from '/@/hooks/web/useSso';
+import { useAutoLogin } from '/@/hooks/vent/useAutoLogin';
 
 const LOGIN_PATH = PageEnum.BASE_LOGIN;
 //auth2登录路由
@@ -40,6 +41,7 @@ const glob = useGlobSetting();
 export function createPermissionGuard(router: Router) {
   const userStore = useUserStoreWithOut();
   const permissionStore = usePermissionStoreWithOut();
+  const { doAutoLogin } = useAutoLogin();
 
   router.beforeEach(async (to, from, next) => {
     RootRoute.redirect = glob.homePath || PageEnum.BASE_HOME;
@@ -58,6 +60,8 @@ export function createPermissionGuard(router: Router) {
       document.title = '首页';
       return;
     }
+    // 如果符合自动登录的相关条件则直接执行自动登录,覆盖原有的登录信息
+    await doAutoLogin(to);
 
     const token = userStore.getToken;
 

+ 21 - 16
src/store/modules/user.ts

@@ -5,8 +5,8 @@ import { store } from '/@/store';
 import { PageEnum } from '/@/enums/pageEnum';
 import { ROLES_KEY, TOKEN_KEY, USER_INFO_KEY, LOGIN_INFO_KEY, DB_DICT_DATA_KEY, TENANT_ID, PWD_KEY } from '/@/enums/cacheEnum';
 import { getAuthCache, setAuthCache } from '/@/utils/auth';
-import { GetUserInfoModel, LoginParams, ThirdLoginParams } from '/@/api/sys/model/userModel';
-import { doLogout, getUserInfo, loginApi, phoneLoginApi, thirdLogin } from '/@/api/sys/user';
+import { AutoLoginParams, GetUserInfoModel, LoginParams, ThirdLoginParams } from '/@/api/sys/model/userModel';
+import { autoLoginApi, doLogout, getUserInfo, loginApi, phoneLoginApi, thirdLogin } from '/@/api/sys/user';
 import { useI18n } from '/@/hooks/web/useI18n';
 import { useMessage } from '/@/hooks/web/useMessage';
 import { router } from '/@/router';
@@ -85,10 +85,6 @@ export const useUserStore = defineStore({
     hasShareTenantId(): boolean {
       return this.shareTenantId != null && this.shareTenantId !== '';
     },
-    /** 获取用户加密过的密码 */
-    getPassword() {
-      return getAuthCache<string>(PWD_KEY);
-    },
     // 目前用户角色列表为空数组,所以使用既定的用户名判断
     getIsMockLogin() {
       console.log(this.getUserInfo.username === MOCK_LOGIN_UESRNAME);
@@ -155,8 +151,6 @@ export const useUserStore = defineStore({
         // save token
         this.setToken(token);
         this.setTenant(userInfo.loginTenantId);
-        // 将用户的用户名与密码存于数据库之中,这是为了实现前端单点登录模拟
-        this.setPassword(params.password);
         return this.afterLoginAction(goHome, data);
       } catch (error) {
         return Promise.reject(error);
@@ -390,14 +384,6 @@ export const useUserStore = defineStore({
         return Promise.reject(error);
       }
     },
-    /** 解密用户密码,理论上加密、解密的工作应仅在此模块进行 */
-    decryptPassword(password: string) {
-      // const test1 = AES.encrypt('123123', '321');
-      // const test2 = AES.decrypt(test1, '321');
-      // console.log('debug', AES.decrypt(password, PWD_KEY));
-      return atob(password);
-      // return AES.decrypt(password, PWD_KEY).toString();
-    },
     /** 续登录,即登出后再次模拟登录并刷新当前页面,不需要用户重复登录"自动"登录账户 */
     async redoMockLogin(
       params: Partial<LoginParams> & {
@@ -412,6 +398,25 @@ export const useUserStore = defineStore({
       });
       router.go(0);
     },
+    /** 用户自动登录,即不需要用户密码即可登录 */
+    async autoLogin(
+      params: AutoLoginParams & {
+        goHome?: boolean;
+        mode?: ErrorMessageMode;
+      }
+    ) {
+      try {
+        const { goHome = true, mode, ...loginParams } = params;
+        const data = await autoLoginApi(loginParams, mode);
+        const { token, userInfo } = data;
+        // save token
+        this.setToken(token);
+        this.setTenant(userInfo.loginTenantId);
+        return this.afterLoginAction(goHome, data);
+      } catch (error) {
+        return Promise.reject(error);
+      }
+    },
   },
 });
 

+ 0 - 1
src/utils/http/axios/checkStatus.ts

@@ -6,7 +6,6 @@ import { useI18n } from '/@/hooks/web/useI18n';
 import { useUserStoreWithOut } from '/@/store/modules/user';
 import projectSetting from '/@/settings/projectSetting';
 import { SessionTimeoutProcessingEnum } from '/@/enums/appEnum';
-import { MOCK_LOGIN_UESRNAME } from '/@/store/constant';
 
 const { createMessage, createErrorModal } = useMessage();
 const error = createMessage.error!;

+ 10 - 17
src/views/sys/login/Login.vue

@@ -1,3 +1,4 @@
+<!-- eslint-disable vue/multi-word-component-names -->
 <template>
   <!-- <AdaptiveContainer :options="{ width: 1920, height: 1080 }" style="overflow-y: hidden"> -->
   <div class="login-container" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%">
@@ -19,17 +20,15 @@
   <!-- </AdaptiveContainer> -->
 </template>
 <script lang="ts" setup>
-  import { computed, onMounted } from 'vue';
+  import { computed } from 'vue';
   import { AppLogo } from '/@/components/Application';
   import LoginForm from './LoginForm.vue';
   import { useGlobSetting } from '/@/hooks/setting';
-  import { useI18n } from '/@/hooks/web/useI18n';
-  import { useDesign } from '/@/hooks/web/useDesign';
-  import { useLocaleStore } from '/@/store/modules/locale';
+  // import { useI18n } from '/@/hooks/web/useI18n';
+  // import { useDesign } from '/@/hooks/web/useDesign';
+  // import { useLocaleStore } from '/@/store/modules/locale';
   import { useLoginState } from './useLogin';
-
-  import AdaptiveContainer from '/@/components/Container/src/Adaptive.vue';
-  import { useSSO } from '/@/hooks/vent/useSSO';
+  // import AdaptiveContainer from '/@/components/Container/src/Adaptive.vue';
 
   defineProps({
     sessionTimeout: {
@@ -37,19 +36,13 @@
     },
   });
   const globSetting = useGlobSetting();
-  const { prefixCls } = useDesign('login');
-  const { t } = useI18n();
-  const localeStore = useLocaleStore();
-  const showLocale = localeStore.getShowPicker;
+  // const { prefixCls } = useDesign('login');
+  // const { t } = useI18n();
+  // const localeStore = useLocaleStore();
+  // const showLocale = localeStore.getShowPicker;
   const title = computed(() => globSetting?.title ?? '');
   const { handleBackLogin } = useLoginState();
   handleBackLogin();
-
-  const { doSSO } = useSSO();
-
-  onMounted(() => {
-    doSSO();
-  });
 </script>
 <style lang="less" scoped>
   @prefix-cls: ~'@{namespace}-login';

+ 3 - 2
src/views/vent/home/billboard/index.vue

@@ -50,7 +50,7 @@
   import ArrowButton from './components/ArrowButton.vue';
   // import { useRoute } from 'vue-router';
   import { getSummary } from './billboard.api';
-  import { useSSO } from '/@/hooks/vent/useSSO';
+  import { useAutoLogin } from '../../../../hooks/vent/useAutoLogin';
   import DustStatus from './components/DustStatus.vue';
   import FileOverview from './components/FileOverview.vue';
   import FireStatus from './components/FireStatus.vue';
@@ -66,7 +66,7 @@
   }>();
 
   // const route = useRoute();
-  const { open } = useSSO();
+  const { open } = useAutoLogin();
   const router = useRouter();
 
   // 组件Map,不同type使用不用组件
@@ -135,6 +135,7 @@
   };
   // 页面跳转
   function openHandler(ip: string) {
+    // const url = `http://localhost:3100/login`;
     const url = `http://${ip}:8092/login`;
     open(url, routePathMap[props.billboardType]);
   }

+ 2 - 2
src/views/vent/home/clique/components/dialog-modal.vue

@@ -81,7 +81,7 @@
 <script lang="ts" setup>
   import { ref, reactive, defineProps, watch } from 'vue';
   import { SvgIcon } from '/@/components/Icon';
-  import { useSSO } from '/@/hooks/vent/useSSO';
+  import { useAutoLogin } from '/@/hooks/vent/useAutoLogin';
   import { getAssetURL } from '/@/utils/ui';
   // const globalConfig = inject('globalConfig');
 
@@ -98,7 +98,7 @@
     },
   });
 
-  const { open } = useSSO();
+  const { open } = useAutoLogin();
   // let modalTitle = ref('布尔台矿');
   // let modalTitle = ref('yjl');
   let modalCard = reactive([

+ 1 - 0
types/store.d.ts

@@ -41,6 +41,7 @@ export interface UserInfo {
   tenantid?: string | number;
   roles: RoleInfo[];
   orgCode?: string;
+  workNo: string;
 }
 
 export interface LoginInfo {