Files
flow-center-front/src/App.vue
T

125 lines
4.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { ref, reactive, computed, onMounted } from "vue";
import layout from "./components/layout.vue";
import { useRouter } from "vue-router";
import config from "@/assets/config/host.config";
import { baseApi } from "@/api/module/base";
import { resolveMenuPage } from "@/utils/menuRoute";
import { Message } from "view-ui-plus";
const router = useRouter();
const isLogin = ref(false);
// 嵌入页旁路(/embed/**,iframe 免签嵌入):子应用 Drawer 里打开,带不了本应用 CAS 会话,
// 也不该出现菜单壳。判定用路由前缀而非 query 标记——刷新/直链/分享均稳定
const isEmbed = computed(() => router.currentRoute.value.path.startsWith("/embed/"));
const layoutData = reactive({
appName: "流程中心",
baseHost: config.baseHost,
ssoHost: config.ssoHost,
appList: [] as any[],
userInfo: null as any,
modList: [] as any[],
isAlone: false,
});
onMounted(async () => {
// 首次导航异步完成:mount 时 currentRoute 可能仍是初始 "/",先等路由就绪再判嵌入前缀,
// 否则直链 /#/embed/* 会在旁路前误发鉴权请求
await router.isReady();
// 嵌入页:跳过两个鉴权请求(失败会弹错误 Message 且渲染带菜单壳的 layout,嵌入场景均不可接受)
if (isEmbed.value) {
isLogin.value = true;
return;
}
try {
// 1. 获取当前用户信息
const user: any = await baseApi.getUserInfo().send();
const { id, name, profilePicture } = user || {};
// 2. 获取当前用户已授权的模块列表
const modList: any[] = await baseApi.getUserMod().send();
layoutData.userInfo = { id, name: name || "管理员", avatar: profilePicture || "" };
layoutData.modList = modList || [];
// 开发环境打印平台原始模块配置,便于排查菜单路径解析问题
if (import.meta.env.DEV) {
console.table(
(modList || []).map((m: any) => ({
name: m.name,
id: m.id,
modId: m.modId,
path: m.page,
}))
);
}
// 有子菜单时不算「单模块独占」模式
const hasChildren = (modList || []).some((m: any) => m.children && m.children.length > 0);
layoutData.isAlone = (modList || []).length <= 1 && !hasChildren;
isLogin.value = true;
// 登录后跳转第一个可用模块("/" 本身即已收到页,无需跳转)
if (router.currentRoute.value.path === "/") {
const firstModule = (modList || [])[0];
const firstRaw = firstModule?.children?.length
? firstModule.children[0]
: firstModule;
const first = resolveMenuPage(firstRaw?.page, firstRaw?.modId ?? firstRaw?.id, firstRaw?.name);
if (!first.external && first.path && first.path !== "/") {
router.replace(first.path);
}
}
} catch (error: any) {
console.error("加载用户信息失败", error);
if (error?.message !== "redirect") {
Message.error("载入用户信息失败,请检查后端服务是否正常!");
}
// 降级:使用默认值("/" 即已收到页,无需跳转)
layoutData.userInfo = { name: "管理员", avatar: "" };
layoutData.modList = [];
layoutData.isAlone = true;
isLogin.value = true;
}
});
</script>
<template>
<!-- 嵌入页:裸渲染,不套 layout 与 base-wrap-main(嵌入页自己管理样式与滚动) -->
<router-view v-if="isEmbed" />
<template v-else>
<layout v-if="isLogin" :layoutData="layoutData" />
<div v-if="isLogin" class="base-wrap-main" :class="{ 'alone-page': layoutData.isAlone }">
<div class="main-wrapper">
<router-view />
</div>
</div>
</template>
</template>
<style lang="scss">
html,
body {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
#app {
height: 100%;
}
/* 页面级滚动容器:main-wrapper 只有 min-height 时内容超一屏会被 body 的
overflow:hidden 直接裁掉(如发通知页),无任何滚动条。定高 + 纵向滚动,
放得下的列表页(表格高度由 Utils.useTableHeight 算好)不受影响 */
.base-wrap-main .main-wrapper {
height: 100%;
overflow-y: auto;
}
/* 表格操作列(operatingHandle 渲染的 Tooltip 包裹层)横排且随单元格居中 */
.ivu-table-cell > .ivu-tooltip {
display: inline-block;
vertical-align: middle;
margin: 0 2px;
}
</style>