mirror of
https://github.com/MCSManager/MCSManager.git
synced 2025-02-05 15:29:35 +08:00
Feat: support open page
This commit is contained in:
parent
98f6b93225
commit
cadc0637a1
@ -53,20 +53,6 @@ import { closeAppLoading } from "./tools/dom";
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
closeAppLoading();
|
closeAppLoading();
|
||||||
|
|
||||||
if (["", "/"].includes(router.currentRoute.value.path.trim())) {
|
|
||||||
if (state.userInfo?.token && !isAdmin.value) {
|
|
||||||
router.push({
|
|
||||||
path: "/customer"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!state.userInfo?.token) {
|
|
||||||
return router.push({
|
|
||||||
path: "/login"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -53,11 +53,17 @@ const menus = computed(() => {
|
|||||||
return router
|
return router
|
||||||
.getRoutes()
|
.getRoutes()
|
||||||
.filter((v) => {
|
.filter((v) => {
|
||||||
return v.meta.mainMenu && isLogged.value;
|
if (containerState.isDesignMode) {
|
||||||
})
|
return v.meta.onlyDisplayEditMode || v.meta.mainMenu;
|
||||||
.filter((v) => {
|
}
|
||||||
if (v.meta.onlyDisplayEditMode) return containerState.isDesignMode;
|
if (isAdmin.value) {
|
||||||
return true;
|
return v.meta.mainMenu === true && v.meta.onlyDisplayEditMode !== true;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
v.meta.mainMenu === true &&
|
||||||
|
isLogged.value &&
|
||||||
|
Number(appState.userInfo?.permission) >= Number(v.meta.permission)
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.map((r) => {
|
.map((r) => {
|
||||||
return {
|
return {
|
||||||
@ -68,20 +74,6 @@ const menus = computed(() => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.beforeEach((to, from) => {
|
|
||||||
console.log("Router:", from, "->", to);
|
|
||||||
if (to.name == null) {
|
|
||||||
router.push({
|
|
||||||
path: "/404",
|
|
||||||
query: {
|
|
||||||
redirect: to.fullPath
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
const breadcrumbs = computed(() => {
|
const breadcrumbs = computed(() => {
|
||||||
const arr = [
|
const arr = [
|
||||||
{
|
{
|
||||||
@ -207,9 +199,9 @@ const appMenus = computed(() => {
|
|||||||
icon: BuildOutlined,
|
icon: BuildOutlined,
|
||||||
click: () => {
|
click: () => {
|
||||||
changeDesignMode(true);
|
changeDesignMode(true);
|
||||||
|
notification.warning({
|
||||||
notification.info({
|
placement: "bottom",
|
||||||
placement: "top",
|
type: "warning",
|
||||||
message: t("TXT_CODE_7b1adf35"),
|
message: t("TXT_CODE_7b1adf35"),
|
||||||
description: t("TXT_CODE_6b6f1d3")
|
description: t("TXT_CODE_6b6f1d3")
|
||||||
});
|
});
|
||||||
|
@ -37,6 +37,7 @@ import InstanceShortcut from "@/widgets/instance/Shortcut.vue";
|
|||||||
import NodeItem from "@/widgets/node/NodeItem.vue";
|
import NodeItem from "@/widgets/node/NodeItem.vue";
|
||||||
import TitleCard from "@/widgets/TitleCard.vue";
|
import TitleCard from "@/widgets/TitleCard.vue";
|
||||||
import LoginCard from "@/widgets/LoginCard.vue";
|
import LoginCard from "@/widgets/LoginCard.vue";
|
||||||
|
import DefaultCard from "@/widgets/DefaultCard.vue";
|
||||||
|
|
||||||
import { NEW_CARD_TYPE } from "../types/index";
|
import { NEW_CARD_TYPE } from "../types/index";
|
||||||
import { ROLE } from "./router";
|
import { ROLE } from "./router";
|
||||||
@ -77,7 +78,8 @@ export const LAYOUT_CARD_TYPES: { [key: string]: any } = {
|
|||||||
ImageManager,
|
ImageManager,
|
||||||
NewImage,
|
NewImage,
|
||||||
Schedule,
|
Schedule,
|
||||||
InstanceShortcut
|
InstanceShortcut,
|
||||||
|
DefaultCard
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface NewCardItem extends LayoutCard {
|
export interface NewCardItem extends LayoutCard {
|
||||||
|
@ -43,6 +43,25 @@ let originRouterConfig: RouterConfig[] = [
|
|||||||
mainMenu: false
|
mainMenu: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/quickstart",
|
||||||
|
name: t("TXT_CODE_2799a1dd"),
|
||||||
|
component: LayoutContainer,
|
||||||
|
meta: {
|
||||||
|
permission: ROLE.ADMIN,
|
||||||
|
mainMenu: false
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/quickstart/minecraft",
|
||||||
|
name: t("TXT_CODE_8d8b1d6a"),
|
||||||
|
component: LayoutContainer,
|
||||||
|
meta: {
|
||||||
|
permission: ROLE.ADMIN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
name: t("TXT_CODE_16d71239"),
|
name: t("TXT_CODE_16d71239"),
|
||||||
@ -178,7 +197,7 @@ let originRouterConfig: RouterConfig[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/404",
|
path: "/404",
|
||||||
name: "404",
|
name: t("页面不存在"),
|
||||||
component: LayoutContainer,
|
component: LayoutContainer,
|
||||||
meta: {
|
meta: {
|
||||||
permission: ROLE.GUEST,
|
permission: ROLE.GUEST,
|
||||||
@ -197,33 +216,22 @@ let originRouterConfig: RouterConfig[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/login",
|
path: "/login",
|
||||||
name: "登录页面",
|
name: t("登录页"),
|
||||||
component: LoginPage,
|
component: LoginPage,
|
||||||
meta: {
|
meta: {
|
||||||
permission: ROLE.GUEST,
|
permission: ROLE.GUEST,
|
||||||
mainMenu: true,
|
|
||||||
onlyDisplayEditMode: true
|
onlyDisplayEditMode: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: "/quickstart",
|
path: "/_open_page",
|
||||||
name: t("TXT_CODE_2799a1dd"),
|
name: t("开放页"),
|
||||||
component: LayoutContainer,
|
component: LayoutContainer,
|
||||||
meta: {
|
meta: {
|
||||||
permission: ROLE.ADMIN,
|
permission: ROLE.ADMIN, // open page without permission
|
||||||
mainMenu: false
|
mainMenu: true,
|
||||||
},
|
onlyDisplayEditMode: true
|
||||||
children: [
|
}
|
||||||
{
|
|
||||||
path: "/quickstart/minecraft",
|
|
||||||
name: t("TXT_CODE_8d8b1d6a"),
|
|
||||||
component: LayoutContainer,
|
|
||||||
meta: {
|
|
||||||
permission: ROLE.ADMIN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -254,8 +262,34 @@ const router = createRouter({
|
|||||||
|
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
const { state } = useAppStateStore();
|
const { state } = useAppStateStore();
|
||||||
const permission = state.userInfo?.permission ?? 0;
|
const userPermission = state.userInfo?.permission ?? 0;
|
||||||
if (Number(to.meta.permission ?? 0) <= permission) {
|
const toPagePermission = Number(to.meta.permission ?? 0);
|
||||||
|
const fromRoutePath = router.currentRoute.value.path.trim();
|
||||||
|
const toRoutePath = to.path.trim();
|
||||||
|
console.info(
|
||||||
|
"Router Changed:",
|
||||||
|
from,
|
||||||
|
"--->",
|
||||||
|
to,
|
||||||
|
"MyPermission:",
|
||||||
|
userPermission,
|
||||||
|
"toPagePermission:",
|
||||||
|
toPagePermission
|
||||||
|
);
|
||||||
|
|
||||||
|
if (toRoutePath.includes("_open_page") || toRoutePath === "/login") {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state.userInfo?.token) return next("/login");
|
||||||
|
|
||||||
|
if (["", "/"].includes(fromRoutePath) && toRoutePath !== "/customer") {
|
||||||
|
if (userPermission === ROLE.USER) {
|
||||||
|
return next("/customer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (to.name && toPagePermission <= userPermission) {
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
next("/404");
|
next("/404");
|
||||||
|
@ -3,11 +3,9 @@ import { ref } from "vue";
|
|||||||
export function useMouseEnter() {
|
export function useMouseEnter() {
|
||||||
const targetId = ref<string>();
|
const targetId = ref<string>();
|
||||||
const handleMouseEnter = (id: string) => {
|
const handleMouseEnter = (id: string) => {
|
||||||
console.log("进入:", id);
|
|
||||||
targetId.value = id;
|
targetId.value = id;
|
||||||
};
|
};
|
||||||
const handleMouseLeave = (id: string) => {
|
const handleMouseLeave = (id: string) => {
|
||||||
console.log("出去:", id);
|
|
||||||
if (targetId.value === id) targetId.value = undefined;
|
if (targetId.value === id) targetId.value = undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,6 +58,16 @@ export const loginUser = useDefineApi<
|
|||||||
method: "POST"
|
method: "POST"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const loginPageInfo = useDefineApi<
|
||||||
|
any,
|
||||||
|
{
|
||||||
|
loginInfo: string;
|
||||||
|
}
|
||||||
|
>({
|
||||||
|
url: "/api/auth/login_info",
|
||||||
|
method: "GET"
|
||||||
|
});
|
||||||
|
|
||||||
export const logoutUser = useDefineApi<any, any>({
|
export const logoutUser = useDefineApi<any, any>({
|
||||||
url: "/api/auth/logout",
|
url: "/api/auth/logout",
|
||||||
method: "GET"
|
method: "GET"
|
||||||
|
59
frontend/src/widgets/DefaultCard.vue
Normal file
59
frontend/src/widgets/DefaultCard.vue
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { t } from "@/lang/i18n";
|
||||||
|
import { useAppStateStore } from "@/stores/useAppStateStore";
|
||||||
|
import type { LayoutCard } from "@/types";
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
card: LayoutCard;
|
||||||
|
}>();
|
||||||
|
const { state, isAdmin } = useAppStateStore();
|
||||||
|
const myAddr = `${window.location.href}`;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<CardPanel class="CardWrapper h-100 w-100" style="height: 100%">
|
||||||
|
<template #title>{{ card.title }}</template>
|
||||||
|
<template #body>
|
||||||
|
<div class="h-100 w-100">
|
||||||
|
<a-empty
|
||||||
|
:image-style="{
|
||||||
|
height: '140px'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #description>
|
||||||
|
<div v-if="isAdmin" class="admin-text">
|
||||||
|
<a-typography-paragraph>
|
||||||
|
<p>
|
||||||
|
{{ t("1. 此页面所有人均可以访问,您也可以放置任何权限的卡片。") }}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{{ t("2. 访问者没有登录或者权限不足,依然会无法加载卡片。") }}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{{ t("3. 设计完成后,您可以使用已登录的状态直接访问。") }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>{{ myAddr }}</pre>
|
||||||
|
</a-typography-paragraph>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<a-typography-paragraph>
|
||||||
|
<p>
|
||||||
|
{{ t("此页面无内容。") }}
|
||||||
|
</p>
|
||||||
|
</a-typography-paragraph>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-empty>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</CardPanel>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.admin-text {
|
||||||
|
text-align: left;
|
||||||
|
max-width: 420px;
|
||||||
|
margin: 20px auto;
|
||||||
|
}
|
||||||
|
</style>
|
@ -7,14 +7,20 @@ import {
|
|||||||
LockOutlined,
|
LockOutlined,
|
||||||
UserOutlined
|
UserOutlined
|
||||||
} from "@ant-design/icons-vue";
|
} from "@ant-design/icons-vue";
|
||||||
import { reactive, ref } from "vue";
|
import { onMounted, reactive, ref } from "vue";
|
||||||
import { router } from "@/config/router";
|
import { router } from "@/config/router";
|
||||||
import { loginUser } from "@/services/apis";
|
import { loginPageInfo, loginUser } from "@/services/apis";
|
||||||
import { sleep } from "@/tools/common";
|
import { sleep } from "@/tools/common";
|
||||||
import { message } from "ant-design-vue";
|
import { message } from "ant-design-vue";
|
||||||
import { useAppStateStore } from "@/stores/useAppStateStore";
|
import { useAppStateStore } from "@/stores/useAppStateStore";
|
||||||
import type { LayoutCard } from "@/types";
|
import type { LayoutCard } from "@/types";
|
||||||
|
import { markdownToHTML } from "@/tools/safe";
|
||||||
|
|
||||||
|
const { state: pageInfoResult, execute } = loginPageInfo();
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await execute();
|
||||||
|
});
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
card: LayoutCard;
|
card: LayoutCard;
|
||||||
}>();
|
}>();
|
||||||
@ -110,6 +116,11 @@ const loginSuccess = () => {
|
|||||||
|
|
||||||
<div class="mt-24 flex-between align-center">
|
<div class="mt-24 flex-between align-center">
|
||||||
<div class="mcsmanager-link">
|
<div class="mcsmanager-link">
|
||||||
|
<div
|
||||||
|
v-if="pageInfoResult?.loginInfo"
|
||||||
|
class="global-markdown-html"
|
||||||
|
v-html="markdownToHTML(pageInfoResult?.loginInfo || '')"
|
||||||
|
></div>
|
||||||
Powered by
|
Powered by
|
||||||
<a href="https://mcsmanager.com" target="_blank" rel="noopener noreferrer">
|
<a href="https://mcsmanager.com" target="_blank" rel="noopener noreferrer">
|
||||||
MCSManager
|
MCSManager
|
||||||
@ -141,6 +152,17 @@ const loginSuccess = () => {
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.mcsmanager-link {
|
||||||
|
.global-markdown-html {
|
||||||
|
text-align: left !important;
|
||||||
|
p {
|
||||||
|
margin: 0px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.loginDone {
|
.loginDone {
|
||||||
.login-page-container {
|
.login-page-container {
|
||||||
|
@ -546,6 +546,19 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
|
|||||||
disableDelete: true
|
disableDelete: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
page: "/_open_page",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: getRandomId(),
|
||||||
|
meta: {},
|
||||||
|
type: "DefaultCard",
|
||||||
|
title: t("关于本页面"),
|
||||||
|
width: 6,
|
||||||
|
height: LayoutCardHeight.SMALL
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user