mirror of https://github.com/halo-dev/halo
feat: add tools page for console (#5252)
#### What type of PR is this? /area console /kind feature /milestone 2.12.x #### What this PR does / why we need it: 为 Console 提供工具页面和菜单项,方便插件集成。 <img width="1920" alt="image" src="https://github.com/halo-dev/halo/assets/21301288/9b63284f-7bdb-4eed-bc6e-cbe2c78359db"> #### Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/5249 #### Special notes for your reviewer: 可以使用以下插件进行测试: 1. [plugin-umami-1.0.0-SNAPSHOT.jar.zip](https://github.com/halo-dev/halo/files/14049119/plugin-umami-1.0.0-SNAPSHOT.jar.zip) 2. [plugin-metrics-graph-1.0.0-beta.1.jar.zip](https://github.com/halo-dev/halo/files/14049127/plugin-metrics-graph-1.0.0-beta.1.jar.zip) 3. [NotifyMe-1.1.0.jar.zip](https://github.com/halo-dev/halo/files/14049131/NotifyMe-1.1.0.jar.zip) #### Does this PR introduce a user-facing change? ```release-note 为 Console 提供工具页面和菜单项,方便插件集成。 ```pull/5256/head
parent
3f27f6f262
commit
22104fe636
|
@ -0,0 +1,98 @@
|
|||
<script lang="ts" setup>
|
||||
import { useRoleStore } from "@/stores/role";
|
||||
import { hasPermission } from "@/utils/permission";
|
||||
import {
|
||||
VPageHeader,
|
||||
IconToolsFill,
|
||||
VCard,
|
||||
VEntity,
|
||||
VEntityField,
|
||||
VButton,
|
||||
VEmpty,
|
||||
} from "@halo-dev/components";
|
||||
import { computed } from "vue";
|
||||
import type { RouteRecordRaw } from "vue-router";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
const router = useRouter();
|
||||
const roleStore = useRoleStore();
|
||||
|
||||
const { uiPermissions } = roleStore.permissions;
|
||||
|
||||
function isRouteValid(route?: RouteRecordRaw) {
|
||||
if (!route) return false;
|
||||
const { meta } = route;
|
||||
if (!meta?.menu) return false;
|
||||
return (
|
||||
!meta.permissions || hasPermission(uiPermissions, meta.permissions, true)
|
||||
);
|
||||
}
|
||||
|
||||
const routes = computed(() => {
|
||||
const matchedRoute = router.currentRoute.value.matched[0];
|
||||
|
||||
return router
|
||||
.getRoutes()
|
||||
.find((route) => route.name === matchedRoute.name)
|
||||
?.children.filter((route) => route.path !== "")
|
||||
.filter((route) => isRouteValid(route));
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VPageHeader :title="$t('core.tool.title')">
|
||||
<template #icon>
|
||||
<IconToolsFill class="mr-2 self-center" />
|
||||
</template>
|
||||
</VPageHeader>
|
||||
|
||||
<div class="m-0 md:m-4">
|
||||
<VCard :body-class="['!p-0']">
|
||||
<VEmpty
|
||||
v-if="!routes?.length"
|
||||
:title="$t('core.tool.empty.title')"
|
||||
:message="$t('core.tool.empty.message')"
|
||||
></VEmpty>
|
||||
<ul
|
||||
v-else
|
||||
class="box-border h-full w-full divide-y divide-gray-100"
|
||||
role="list"
|
||||
>
|
||||
<li v-for="route in routes" :key="route.name">
|
||||
<VEntity>
|
||||
<template #start>
|
||||
<VEntityField>
|
||||
<template #description>
|
||||
<component
|
||||
:is="route.meta?.menu?.icon"
|
||||
v-if="route.meta?.menu?.icon"
|
||||
class="text-lg"
|
||||
/>
|
||||
<IconToolsFill v-else class="text-lg" />
|
||||
</template>
|
||||
</VEntityField>
|
||||
<VEntityField
|
||||
:route="{ name: route.name }"
|
||||
:title="route.meta?.menu?.name"
|
||||
:description="route.meta?.description"
|
||||
></VEntityField>
|
||||
</template>
|
||||
|
||||
<template #end>
|
||||
<VEntityField>
|
||||
<template #description>
|
||||
<VButton
|
||||
size="sm"
|
||||
@click="$router.push({ name: route.name })"
|
||||
>
|
||||
{{ $t("core.common.buttons.access") }}
|
||||
</VButton>
|
||||
</template>
|
||||
</VEntityField>
|
||||
</template>
|
||||
</VEntity>
|
||||
</li>
|
||||
</ul>
|
||||
</VCard>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,32 @@
|
|||
import { definePlugin } from "@halo-dev/console-shared";
|
||||
import Tools from "./Tools.vue";
|
||||
import { markRaw } from "vue";
|
||||
import BasicLayout from "@console/layouts/BasicLayout.vue";
|
||||
import { IconToolsFill } from "@halo-dev/components";
|
||||
|
||||
export default definePlugin({
|
||||
components: {},
|
||||
routes: [
|
||||
{
|
||||
path: "/tools",
|
||||
name: "ToolsRoot",
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
title: "core.tool.title",
|
||||
menu: {
|
||||
name: "core.sidebar.menu.items.tools",
|
||||
group: "system",
|
||||
icon: markRaw(IconToolsFill),
|
||||
priority: 5,
|
||||
},
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
name: "Tools",
|
||||
component: Tools,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
|
@ -71,6 +71,7 @@ import IconLogoutCircleRLine from "~icons/ri/logout-circle-r-line";
|
|||
import IconAccountCircleLine from "~icons/ri/account-circle-line";
|
||||
import IconSettings3Line from "~icons/ri/settings-3-line";
|
||||
import IconImageAddLine from "~icons/ri/image-add-line";
|
||||
import IconToolsFill from "~icons/ri/tools-fill";
|
||||
|
||||
export {
|
||||
IconDashboard,
|
||||
|
@ -146,4 +147,5 @@ export {
|
|||
IconAccountCircleLine,
|
||||
IconSettings3Line,
|
||||
IconImageAddLine,
|
||||
IconToolsFill,
|
||||
};
|
||||
|
|
|
@ -77,6 +77,7 @@ core:
|
|||
settings: Settings
|
||||
actuator: Actuator
|
||||
backup: Backup
|
||||
tools: Tools
|
||||
operations:
|
||||
logout:
|
||||
tooltip: Logout
|
||||
|
@ -1495,6 +1496,7 @@ core:
|
|||
view_all: View all
|
||||
verify: Verify
|
||||
modify: Modify
|
||||
access: Access
|
||||
radio:
|
||||
"yes": "Yes"
|
||||
"no": "No"
|
||||
|
@ -1601,3 +1603,10 @@ core:
|
|||
toast_success: >-
|
||||
If your username and email address match, we will send an email to
|
||||
your email address.
|
||||
tool:
|
||||
title: Tools
|
||||
empty:
|
||||
title: There are no tools available
|
||||
message: >-
|
||||
There are currently no tools available, and system tools may be provided
|
||||
by plugins
|
||||
|
|
|
@ -75,6 +75,7 @@ core:
|
|||
settings: 设置
|
||||
actuator: 概览
|
||||
backup: 备份
|
||||
tools: 工具
|
||||
operations:
|
||||
logout:
|
||||
tooltip: 退出登录
|
||||
|
@ -1441,6 +1442,7 @@ core:
|
|||
view_all: 查看全部
|
||||
verify: 验证
|
||||
modify: 修改
|
||||
access: 访问
|
||||
radio:
|
||||
"yes": 是
|
||||
"no": 否
|
||||
|
@ -1509,3 +1511,8 @@ core:
|
|||
recovering: 恢复中
|
||||
fields:
|
||||
post_count: "{count} 篇文章"
|
||||
tool:
|
||||
title: 工具
|
||||
empty:
|
||||
title: 没有可用工具
|
||||
message: 当前没有可用的工具,系统工具可能由插件提供
|
||||
|
|
|
@ -75,6 +75,7 @@ core:
|
|||
settings: 設置
|
||||
actuator: 概覽
|
||||
backup: 備份
|
||||
tools: 工具
|
||||
operations:
|
||||
logout:
|
||||
tooltip: 登出
|
||||
|
@ -1407,6 +1408,7 @@ core:
|
|||
view_all: 查看全部
|
||||
modify: 修改
|
||||
verify: 驗證
|
||||
access: 访问
|
||||
radio:
|
||||
"yes": 是
|
||||
"no": 否
|
||||
|
@ -1509,3 +1511,8 @@ core:
|
|||
send:
|
||||
label: 發送驗證郵件
|
||||
toast_success: 如果你的用戶名和郵箱地址匹配,我們將會發送一封郵件到你的郵箱。
|
||||
tool:
|
||||
title: 工具
|
||||
empty:
|
||||
title: 沒有可用工具
|
||||
message: 目前沒有可用的工具,系統工具可能由外掛提供
|
||||
|
|
Loading…
Reference in New Issue