feat: add pages extension points

Signed-off-by: Ryan Wang <i@ryanc.cc>
pull/588/head
Ryan Wang 2022-06-23 15:31:32 +08:00
parent 4ef9f0cf5d
commit c97a3c8836
8 changed files with 71 additions and 58 deletions

View File

@ -1,3 +1,4 @@
export * from "./types/plugin"; export * from "./types/plugin";
export * from "./types/menus"; export * from "./types/menus";
export * from "./core/plugins"; export * from "./core/plugins";
export * from "./states/pages";

View File

@ -0,0 +1,9 @@
export interface PagesPublicState {
functionalPages: FunctionalPagesState[];
}
export interface FunctionalPagesState {
name: string;
path: string;
url?: string;
}

View File

@ -1,15 +1,11 @@
import type { Component } from "vue"; import type { Component, Ref } from "vue";
import type { RouteRecordRaw } from "vue-router"; import type { RouteRecordRaw } from "vue-router";
import type { MenuGroupType } from "./menus"; import type { MenuGroupType } from "./menus";
import type { PagesPublicState } from "@/states/pages";
export type ExtensionPointName = export type ExtensionPointName = "PAGES" | "POSTS";
| "POSTS"
| "POST_EDITOR"
| "DASHBOARD"
| "USER_SETTINGS";
// TODO define extension point state export type ExtensionPointState = PagesPublicState;
export type ExtensionPointState = Record<string, unknown>;
export interface Plugin { export interface Plugin {
name: string; name: string;
@ -33,8 +29,7 @@ export interface Plugin {
menus?: MenuGroupType[]; menus?: MenuGroupType[];
extensionPoints?: Record< extensionPoints?: {
ExtensionPointName, [key in ExtensionPointName]?: (state: Ref<ExtensionPointState>) => void;
(state: ExtensionPointState) => void };
>;
} }

View File

@ -0,0 +1,21 @@
import { usePluginStore } from "@/stores/plugin";
import type {
ExtensionPointName,
ExtensionPointState,
} from "@halo-dev/admin-shared";
import type { Plugin } from "@/types/extension";
import type { Ref } from "vue";
export function useExtensionPointsState(
point: ExtensionPointName,
state: Ref<ExtensionPointState>
) {
const { plugins } = usePluginStore();
plugins.forEach((plugin: Plugin) => {
if (!plugin.spec.module?.extensionPoints?.[point]) {
return;
}
plugin.spec.module.extensionPoints[point]?.(state);
});
}

View File

@ -14,9 +14,10 @@ import {
} from "@halo-dev/components"; } from "@halo-dev/components";
import { ref } from "vue"; import { ref } from "vue";
import { users } from "@/modules/system/users/users-mock"; import { users } from "@/modules/system/users/users-mock";
import halo from "@/assets/logo.svg"; import type { PagesPublicState } from "@halo-dev/admin-shared";
import { useExtensionPointsState } from "@/composables/usePlugins";
const sheetsRef = ref([ const pagesRef = ref([
{ {
title: "关于我们", title: "关于我们",
url: "/about", url: "/about",
@ -37,29 +38,13 @@ const sheetsRef = ref([
}, },
]); ]);
const advancedSheets = ref([ const activeId = ref("functional");
{
name: "友情链接",
author: "halo-dev",
logo: halo,
url: "/links",
},
{
name: "图库",
author: "halo-dev",
logo: halo,
url: "/photos",
},
{
name: "社区",
author: "halo-dev",
logo: halo,
url: "/community",
},
]);
const checkAll = ref(false); const checkAll = ref(false);
const activeId = ref("advanced"); const pagesPublicState = ref<PagesPublicState>({
functionalPages: [],
});
useExtensionPointsState("PAGES", pagesPublicState);
</script> </script>
<template> <template>
<VPageHeader title="页面"> <VPageHeader title="页面">
@ -82,19 +67,23 @@ const activeId = ref("advanced");
<VTabbar <VTabbar
v-model:active-id="activeId" v-model:active-id="activeId"
:items="[ :items="[
{ id: 'advanced', label: '功能页面' }, { id: 'functional', label: '功能页面' },
{ id: 'custom', label: '自定义页面' }, { id: 'custom', label: '自定义页面' },
]" ]"
class="w-full !rounded-none" class="w-full !rounded-none"
type="outline" type="outline"
></VTabbar> ></VTabbar>
</template> </template>
<div v-if="activeId === 'advanced'"> <div v-if="activeId === 'functional'">
<ul <ul
class="box-border h-full w-full divide-y divide-gray-100" class="box-border h-full w-full divide-y divide-gray-100"
role="list" role="list"
> >
<li v-for="(sheet, index) in advancedSheets" :key="index"> <li
v-for="(page, index) in pagesPublicState.functionalPages"
:key="index"
@click="$router.push({ path: page.path })"
>
<div <div
class="relative block cursor-pointer px-4 py-3 transition-all hover:bg-gray-50" class="relative block cursor-pointer px-4 py-3 transition-all hover:bg-gray-50"
> >
@ -104,20 +93,15 @@ const activeId = ref("advanced");
<span <span
class="mr-0 truncate text-sm font-medium text-gray-900 sm:mr-2" class="mr-0 truncate text-sm font-medium text-gray-900 sm:mr-2"
> >
{{ sheet.name }} {{ page.name }}
</span> </span>
<VTag>{{ sheet.url }}</VTag> <VTag>{{ page.url }}</VTag>
</div> </div>
</div> </div>
<div class="flex"> <div class="flex">
<div <div
class="inline-flex flex-col flex-col-reverse items-end gap-4 sm:flex-row sm:items-center sm:gap-6" class="inline-flex flex-col flex-col-reverse items-end gap-4 sm:flex-row sm:items-center sm:gap-6"
> >
<img
v-tooltip="`由${sheet.name}插件提供`"
:src="sheet.logo"
class="hidden h-6 w-6 rounded-full ring-2 ring-white sm:inline-block"
/>
<span class="cursor-pointer"> <span class="cursor-pointer">
<IconSettings /> <IconSettings />
</span> </span>
@ -269,7 +253,7 @@ const activeId = ref("advanced");
class="box-border h-full w-full divide-y divide-gray-100" class="box-border h-full w-full divide-y divide-gray-100"
role="list" role="list"
> >
<li v-for="(sheet, index) in sheetsRef" :key="index"> <li v-for="(page, index) in pagesRef" :key="index">
<div <div
:class="{ :class="{
'bg-gray-100': checkAll, 'bg-gray-100': checkAll,
@ -293,17 +277,17 @@ const activeId = ref("advanced");
<span <span
class="mr-0 truncate text-sm font-medium text-gray-900 sm:mr-2" class="mr-0 truncate text-sm font-medium text-gray-900 sm:mr-2"
> >
{{ sheet.title }} {{ page.title }}
</span> </span>
<VTag>{{ sheet.url }}</VTag> <VTag>{{ page.url }}</VTag>
</div> </div>
<div class="mt-1 flex"> <div class="mt-1 flex">
<VSpace> <VSpace>
<span class="text-xs text-gray-500"> <span class="text-xs text-gray-500">
访问量 {{ sheet.views }} 访问量 {{ page.views }}
</span> </span>
<span class="text-xs text-gray-500"> <span class="text-xs text-gray-500">
评论 {{ sheet.commentCount }} 评论 {{ page.commentCount }}
</span> </span>
</VSpace> </VSpace>
</div> </div>

View File

@ -1,19 +1,19 @@
import { definePlugin } from "@halo-dev/admin-shared"; import { definePlugin } from "@halo-dev/admin-shared";
import { BasicLayout } from "@/layouts"; import { BasicLayout } from "@/layouts";
import SheetList from "./SheetList.vue"; import SheetList from "./PageList.vue";
import { IconPages } from "@halo-dev/components"; import { IconPages } from "@halo-dev/components";
export default definePlugin({ export default definePlugin({
name: "sheetModule", name: "pageModule",
components: [], components: [],
routes: [ routes: [
{ {
path: "/sheets", path: "/pages",
component: BasicLayout, component: BasicLayout,
children: [ children: [
{ {
path: "", path: "",
name: "Sheets", name: "Pages",
component: SheetList, component: SheetList,
}, },
], ],
@ -25,7 +25,7 @@ export default definePlugin({
items: [ items: [
{ {
name: "页面", name: "页面",
path: "/sheets", path: "/pages",
icon: IconPages, icon: IconPages,
}, },
], ],

View File

@ -1,6 +1,6 @@
import dashboardModule from "./dashboard/module"; import dashboardModule from "./dashboard/module";
import postModule from "./contents/posts/module"; import postModule from "./contents/posts/module";
import sheetModule from "./contents/sheets/module"; import pageModule from "./contents/pages/module";
import commentModule from "./contents/comments/module"; import commentModule from "./contents/comments/module";
import attachmentModule from "./contents/attachments/module"; import attachmentModule from "./contents/attachments/module";
import themeModule from "./interface/themes/module"; import themeModule from "./interface/themes/module";
@ -13,7 +13,7 @@ import settingModule from "./system/settings/module";
const coreModules = [ const coreModules = [
dashboardModule, dashboardModule,
postModule, postModule,
sheetModule, pageModule,
commentModule, commentModule,
attachmentModule, attachmentModule,
themeModule, themeModule,

View File

@ -1,3 +1,5 @@
import type { Plugin as PluginModule } from "@halo-dev/admin-shared";
export interface License { export interface License {
name?: string; name?: string;
url?: string; url?: string;
@ -44,6 +46,7 @@ export interface PluginSpec {
requires?: string; requires?: string;
pluginClass?: string; pluginClass?: string;
enabled?: boolean; enabled?: boolean;
module?: PluginModule;
} }
export interface PluginStatus { export interface PluginStatus {