Feat: support open page

This commit is contained in:
unitwk 2023-12-03 11:56:19 +08:00
parent 98f6b93225
commit cadc0637a1
9 changed files with 178 additions and 62 deletions

View File

@ -53,20 +53,6 @@ import { closeAppLoading } from "./tools/dom";
onMounted(async () => {
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>

View File

@ -53,11 +53,17 @@ const menus = computed(() => {
return router
.getRoutes()
.filter((v) => {
return v.meta.mainMenu && isLogged.value;
})
.filter((v) => {
if (v.meta.onlyDisplayEditMode) return containerState.isDesignMode;
return true;
if (containerState.isDesignMode) {
return v.meta.onlyDisplayEditMode || v.meta.mainMenu;
}
if (isAdmin.value) {
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) => {
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 arr = [
{
@ -207,9 +199,9 @@ const appMenus = computed(() => {
icon: BuildOutlined,
click: () => {
changeDesignMode(true);
notification.info({
placement: "top",
notification.warning({
placement: "bottom",
type: "warning",
message: t("TXT_CODE_7b1adf35"),
description: t("TXT_CODE_6b6f1d3")
});

View File

@ -37,6 +37,7 @@ import InstanceShortcut from "@/widgets/instance/Shortcut.vue";
import NodeItem from "@/widgets/node/NodeItem.vue";
import TitleCard from "@/widgets/TitleCard.vue";
import LoginCard from "@/widgets/LoginCard.vue";
import DefaultCard from "@/widgets/DefaultCard.vue";
import { NEW_CARD_TYPE } from "../types/index";
import { ROLE } from "./router";
@ -77,7 +78,8 @@ export const LAYOUT_CARD_TYPES: { [key: string]: any } = {
ImageManager,
NewImage,
Schedule,
InstanceShortcut
InstanceShortcut,
DefaultCard
};
export interface NewCardItem extends LayoutCard {

View File

@ -43,6 +43,25 @@ let originRouterConfig: RouterConfig[] = [
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: "/",
name: t("TXT_CODE_16d71239"),
@ -178,7 +197,7 @@ let originRouterConfig: RouterConfig[] = [
},
{
path: "/404",
name: "404",
name: t("页面不存在"),
component: LayoutContainer,
meta: {
permission: ROLE.GUEST,
@ -197,33 +216,22 @@ let originRouterConfig: RouterConfig[] = [
},
{
path: "/login",
name: "登录页",
name: t("登录页"),
component: LoginPage,
meta: {
permission: ROLE.GUEST,
mainMenu: true,
onlyDisplayEditMode: true
}
},
{
path: "/quickstart",
name: t("TXT_CODE_2799a1dd"),
path: "/_open_page",
name: t("开放页"),
component: LayoutContainer,
meta: {
permission: ROLE.ADMIN,
mainMenu: false
},
children: [
{
path: "/quickstart/minecraft",
name: t("TXT_CODE_8d8b1d6a"),
component: LayoutContainer,
meta: {
permission: ROLE.ADMIN
}
}
]
permission: ROLE.ADMIN, // open page without permission
mainMenu: true,
onlyDisplayEditMode: true
}
}
];
@ -254,8 +262,34 @@ const router = createRouter({
router.beforeEach((to, from, next) => {
const { state } = useAppStateStore();
const permission = state.userInfo?.permission ?? 0;
if (Number(to.meta.permission ?? 0) <= permission) {
const userPermission = state.userInfo?.permission ?? 0;
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();
} else {
next("/404");

View File

@ -3,11 +3,9 @@ import { ref } from "vue";
export function useMouseEnter() {
const targetId = ref<string>();
const handleMouseEnter = (id: string) => {
console.log("进入:", id);
targetId.value = id;
};
const handleMouseLeave = (id: string) => {
console.log("出去:", id);
if (targetId.value === id) targetId.value = undefined;
};

View File

@ -58,6 +58,16 @@ export const loginUser = useDefineApi<
method: "POST"
});
export const loginPageInfo = useDefineApi<
any,
{
loginInfo: string;
}
>({
url: "/api/auth/login_info",
method: "GET"
});
export const logoutUser = useDefineApi<any, any>({
url: "/api/auth/logout",
method: "GET"

View 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>

View File

@ -7,14 +7,20 @@ import {
LockOutlined,
UserOutlined
} from "@ant-design/icons-vue";
import { reactive, ref } from "vue";
import { onMounted, reactive, ref } from "vue";
import { router } from "@/config/router";
import { loginUser } from "@/services/apis";
import { loginPageInfo, loginUser } from "@/services/apis";
import { sleep } from "@/tools/common";
import { message } from "ant-design-vue";
import { useAppStateStore } from "@/stores/useAppStateStore";
import type { LayoutCard } from "@/types";
import { markdownToHTML } from "@/tools/safe";
const { state: pageInfoResult, execute } = loginPageInfo();
onMounted(async () => {
await execute();
});
const props = defineProps<{
card: LayoutCard;
}>();
@ -110,6 +116,11 @@ const loginSuccess = () => {
<div class="mt-24 flex-between align-center">
<div class="mcsmanager-link">
<div
v-if="pageInfoResult?.loginInfo"
class="global-markdown-html"
v-html="markdownToHTML(pageInfoResult?.loginInfo || '')"
></div>
Powered by
<a href="https://mcsmanager.com" target="_blank" rel="noopener noreferrer">
MCSManager
@ -141,6 +152,17 @@ const loginSuccess = () => {
</div>
</template>
<style>
.mcsmanager-link {
.global-markdown-html {
text-align: left !important;
p {
margin: 0px !important;
}
}
}
</style>
<style lang="scss" scoped>
.loginDone {
.login-page-container {

View File

@ -546,6 +546,19 @@ function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
disableDelete: true
}
]
},
{
page: "/_open_page",
items: [
{
id: getRandomId(),
meta: {},
type: "DefaultCard",
title: t("关于本页面"),
width: 6,
height: LayoutCardHeight.SMALL
}
]
}
];
}