Skip to content
On this page

单点登录

OA 单点登录 SRM 并跳转至各模块审批详情页面

TIP

项目开发通常需要对接 OA 等系统,并实现单点登录并跳转至各模块审批详情页面的需求。

- 代码实现

  1. 约定 url 跳转地址格式, 比如: https://srmtest.jianlibao.net:18080/user/login?redirect=/srm/bpm/before/1271184036781359104&token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3NDEyNTQyMjgsImFjY291bnQiOiIxNjY0Mjk5XzEwMDEifQ.2dod8Vjp0mIPYKzh9ZTqwvZY3y43gOum3XYkNqtU8ZE
  2. 本地路由,用一个中间页面作数据处理,如上述的 /srm/bpm/before/:id
  3. 组装实现业务跳转逻辑代码
vue
<script lang="ts" setup>
const resetStore = () => {
  nextTick(() => {
    // 清空各模块列表页当前行缓存数据
    pageStore.$reset();
    // 清空当前登录人动态授权信息
    userStore.$reset();
    // 清空动态路由权限
    permissionStore.$reset();
    // 清空tabs
    tabsStore.$reset();
  });
};

const loginByToken = () => {
  let token = route.query?.token;
  if (token) {
    resetStore(); // 需要清除 token 缓存
    loginLoading.value = true;
    Request.registerModuleAction("LoginModule/loginByToken", {
      token: token,
    }).then((res) => {
      loginLoading.value = false;
      if (res && res.success) {
        onLginFinish(res);
      } else {
        Message.error(res.message);
        router.replace({ path: "/user/login" });
      }
    });
  }
};
</script>
ts
export const secondDevRoutes = [
  {
    path: "/srm/bpm/before/:id",
    route: "1",
    meta: {
      keepAlive: false,
      title: "待办审批跳转",
      titleI18nKey: "",
    },
    name: "srm-bpm-before",
    component: () => import("@views/secondDev/bpm/task/before.vue"),
  },
];
vue
<!--
 * @Author: wangxin
 * @Date: 2024-07-31 16:13:07
 * @LastEditors: wangxin wangxin@51qqt.com
 * @LastEditTime: 2024-11-04 10:56:08
 * @Description: 待办审批跳转页面
 * @FilePath: /jianlibao_240625/src/views/secondDev/bpm/task/before.vue
-->
<template>
  <div class="ToDoBefore">
    <a-spin :spinning="loading">
      <div class="container">
        <div class="wrapper">
          <div class="content">
            <div class="info">
              <QSymbolIcon class="icon" type="icon-Q-success" :size="380" />
              <div class="tip">
                <h5 class="ant-typography" v-if="loading">
                  <span class="ant-typography ant-typography-danger"
                    >加载中...</span
                  >
                </h5>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div v-if="loading" class="loading">Loading...</div>
    </a-spin>
  </div>
</template>

<script setup lang="ts">
import { ref, watch } from "vue";
import { useRoute } from "vue-router";
import qqtApi from "@qqt-product/api";

import { QSymbolIcon } from "@qqt-product/icons";

import type {
  GlobalPageLayoutTypes,
  GlobalListPageLayoutTypes,
} from "@qqt-product/ui";

import useJumpDetailHook from "@/views/srm/bpm/hook/useJumpDetailHook";

// 工具函数及types
import qqtUtils from "@qqt-product/utils";

const { delay } = qqtUtils;

const route = useRoute();
const Request: qqtApi.Request = qqtApi.useHttp();

const useJumpDetail = useJumpDetailHook();

const listLayoutRef = ref<any>({});

const loading = ref<boolean>(true);

const fetchData = (id: string) => {
  if (!id) {
    return;
  }

  const url = "/a1bpmn/audit/api/runtime/admin/processInstance/detail";
  const params = {
    processInstanceId: id,
  };
  Request.get({ url, params }).then((res) => {
    if (res.success) {
      const todoTaskList = res.result
        .todoTaskList as GlobalPageLayoutTypes.RecordString[];
      if (todoTaskList && todoTaskList.length) {
        delay(() => {
          const row = todoTaskList[0];
          useJumpDetail.jumpDetail(
            { row } as GlobalListPageLayoutTypes.ListOptionsEventParams,
            listLayoutRef,
            false
          );
        }, 300);
      }
    }
  });
};

// watch the params of the route to fetch the data again
watch(
  () => route.params.id,
  (id) => fetchData(id as string),
  { immediate: true }
);
</script>

<style lang="less" scoped>
.ToDoBefore {
  .container {
    background-color: #eff2f5;
    padding: 12px;
    height: 100vh;
  }
  .wrapper {
    position: relative;
    border-radius: 12px;
    background: #fff;
    width: calc(100vw - 24px);
    height: calc(100vh - 24px);
    min-width: 1000px;
  }
  .content {
    position: absolute;
    left: 50%;
    top: 30%;
    transform: translate(-50%, -30%);
  }
  .info {
    display: flex;
    flex-direction: column;
  }
  .tip {
    text-align: center;
  }
}
</style>