feat: add entity param for list item operation extension point (#4515)

#### What type of PR is this?

/area console
/kind feature
/milestone 2.9.x

#### What this PR does / why we need it:

Halo 在 https://github.com/halo-dev/halo/pull/4452 中为数据列表的操作选项添加了拓展点,用于通过插件扩展操作选项。但忽略了操作选项的组件需要自定义并且自行处理点击事件,这个时候组件应该比较难拿到数据列表项的数据。

此 PR 对此进行优化,在扩展点方法传入了需要的数据。

#### Does this PR introduce a user-facing change?

```release-note
None
```
pull/4523/head
Ryan Wang 2023-08-30 22:36:13 -05:00 committed by GitHub
parent 9c875e1731
commit 329b389d60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 38 additions and 24 deletions

View File

@ -8,9 +8,9 @@
目前支持扩展的数据列表: 目前支持扩展的数据列表:
- 文章:`"post:list-item:operation:create"?: () => | EntityDropdownItem<ListedPost>[] | Promise<EntityDropdownItem<ListedPost>[]>` - 文章:`"post:list-item:operation:create"?: (post: Ref<ListedPost>) => | EntityDropdownItem<ListedPost>[] | Promise<EntityDropdownItem<ListedPost>[]>`
- 插件:`"plugin:list-item:operation:create"?: () => | EntityDropdownItem<Plugin>[] | Promise<EntityDropdownItem<Plugin>[]>` - 插件:`"plugin:list-item:operation:create"?: (plugin: Ref<Plugin>) => | EntityDropdownItem<Plugin>[] | Promise<EntityDropdownItem<Plugin>[]>`
- 备份:`"backup:list-item:operation:create"?: () => | EntityDropdownItem<Backup>[] | Promise<EntityDropdownItem<Backup>[]>` - 备份:`"backup:list-item:operation:create"?: (backup: Ref<Backup>) => | EntityDropdownItem<Backup>[] | Promise<EntityDropdownItem<Backup>[]>`
示例: 示例:

View File

@ -40,17 +40,19 @@ export interface ExtensionPoint {
| PluginInstallationTab[] | PluginInstallationTab[]
| Promise<PluginInstallationTab[]>; | Promise<PluginInstallationTab[]>;
"post:list-item:operation:create"?: () => "post:list-item:operation:create"?: (
post: Ref<ListedPost>
) =>
| EntityDropdownItem<ListedPost>[] | EntityDropdownItem<ListedPost>[]
| Promise<EntityDropdownItem<ListedPost>[]>; | Promise<EntityDropdownItem<ListedPost>[]>;
"plugin:list-item:operation:create"?: () => "plugin:list-item:operation:create"?: (
| EntityDropdownItem<Plugin>[] plugin: Ref<Plugin>
| Promise<EntityDropdownItem<Plugin>[]>; ) => EntityDropdownItem<Plugin>[] | Promise<EntityDropdownItem<Plugin>[]>;
"backup:list-item:operation:create"?: () => "backup:list-item:operation:create"?: (
| EntityDropdownItem<Backup>[] backup: Ref<Backup>
| Promise<EntityDropdownItem<Backup>[]>; ) => EntityDropdownItem<Backup>[] | Promise<EntityDropdownItem<Backup>[]>;
"plugin:list-item:field:create"?: ( "plugin:list-item:field:create"?: (
plugin: Ref<Plugin> plugin: Ref<Plugin>

View File

@ -5,15 +5,16 @@ import type {
EntityFieldItem, EntityFieldItem,
PluginModule, PluginModule,
} from "@halo-dev/console-shared"; } from "@halo-dev/console-shared";
import { onMounted, ref, type Ref, computed, type ComputedRef } from "vue"; import { onMounted, ref, type ComputedRef, type Ref, computed } from "vue";
export function useEntityDropdownItemExtensionPoint<T>( export function useEntityDropdownItemExtensionPoint<T>(
extensionPointName: string, extensionPointName: string,
presets: EntityDropdownItem<T>[] entity: Ref<T>,
presets: ComputedRef<EntityDropdownItem<T>[]>
) { ) {
const { pluginModules } = usePluginModuleStore(); const { pluginModules } = usePluginModuleStore();
const dropdownItems = ref<EntityDropdownItem<T>[]>(presets); const itemsFromPlugins = ref<EntityDropdownItem<T>[]>([]);
onMounted(() => { onMounted(() => {
pluginModules.forEach((pluginModule: PluginModule) => { pluginModules.forEach((pluginModule: PluginModule) => {
@ -22,14 +23,16 @@ export function useEntityDropdownItemExtensionPoint<T>(
return; return;
} }
const items = extensionPoints[ const items = extensionPoints[extensionPointName](
extensionPointName entity
]() as EntityDropdownItem<T>[]; ) as EntityDropdownItem<T>[];
dropdownItems.value.push(...items); itemsFromPlugins.value.push(...items);
}); });
});
dropdownItems.value.sort((a, b) => { const dropdownItems = computed(() => {
return [...presets.value, ...itemsFromPlugins.value].sort((a, b) => {
return a.priority - b.priority; return a.priority - b.priority;
}); });
}); });

View File

@ -29,6 +29,7 @@ import { markRaw } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { useEntityDropdownItemExtensionPoint } from "@/composables/use-entity-extension-points"; import { useEntityDropdownItemExtensionPoint } from "@/composables/use-entity-extension-points";
import EntityDropdownItems from "@/components/entity/EntityDropdownItems.vue"; import EntityDropdownItems from "@/components/entity/EntityDropdownItems.vue";
import { toRefs } from "vue";
const { currentUserHasPermission } = usePermission(); const { currentUserHasPermission } = usePermission();
const { t } = useI18n(); const { t } = useI18n();
@ -45,6 +46,8 @@ const props = withDefaults(
} }
); );
const { post } = toRefs(props);
const emit = defineEmits<{ const emit = defineEmits<{
(event: "open-setting-modal", post: Post): void; (event: "open-setting-modal", post: Post): void;
}>(); }>();
@ -121,7 +124,8 @@ const handleDelete = async () => {
const { dropdownItems } = useEntityDropdownItemExtensionPoint<ListedPost>( const { dropdownItems } = useEntityDropdownItemExtensionPoint<ListedPost>(
"post:list-item:operation:create", "post:list-item:operation:create",
[ post,
computed(() => [
{ {
priority: 10, priority: 10,
component: markRaw(VDropdownItem), component: markRaw(VDropdownItem),
@ -161,7 +165,7 @@ const { dropdownItems } = useEntityDropdownItemExtensionPoint<ListedPost>(
permissions: [], permissions: [],
action: handleDelete, action: handleDelete,
}, },
] ])
); );
</script> </script>

View File

@ -17,6 +17,7 @@ import prettyBytes from "pretty-bytes";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useEntityDropdownItemExtensionPoint } from "@/composables/use-entity-extension-points"; import { useEntityDropdownItemExtensionPoint } from "@/composables/use-entity-extension-points";
import EntityDropdownItems from "@/components/entity/EntityDropdownItems.vue"; import EntityDropdownItems from "@/components/entity/EntityDropdownItems.vue";
import { toRefs } from "vue";
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { t } = useI18n(); const { t } = useI18n();
@ -25,6 +26,8 @@ const props = defineProps<{
backup: Backup; backup: Backup;
}>(); }>();
const { backup } = toRefs(props);
type Phase = { type Phase = {
text: string; text: string;
state: "default" | "warning" | "success" | "error"; state: "default" | "warning" | "success" | "error";
@ -99,7 +102,8 @@ function handleDelete() {
const { dropdownItems } = useEntityDropdownItemExtensionPoint<Backup>( const { dropdownItems } = useEntityDropdownItemExtensionPoint<Backup>(
"backup:list-item:operation:create", "backup:list-item:operation:create",
[ backup,
computed(() => [
{ {
priority: 10, priority: 10,
component: markRaw(VDropdownItem), component: markRaw(VDropdownItem),
@ -118,7 +122,7 @@ const { dropdownItems } = useEntityDropdownItemExtensionPoint<Backup>(
visible: true, visible: true,
action: () => handleDelete(), action: () => handleDelete(),
}, },
] ])
); );
</script> </script>

View File

@ -78,7 +78,8 @@ const handleResetSettingConfig = async () => {
const { dropdownItems } = useEntityDropdownItemExtensionPoint<Plugin>( const { dropdownItems } = useEntityDropdownItemExtensionPoint<Plugin>(
"plugin:list-item:operation:create", "plugin:list-item:operation:create",
[ plugin,
computed(() => [
{ {
priority: 10, priority: 10,
component: markRaw(VDropdownItem), component: markRaw(VDropdownItem),
@ -150,7 +151,7 @@ const { dropdownItems } = useEntityDropdownItemExtensionPoint<Plugin>(
handleResetSettingConfig(); handleResetSettingConfig();
}, },
}, },
] ])
); );
const { startFields, endFields } = useEntityFieldItemExtensionPoint<Plugin>( const { startFields, endFields } = useEntityFieldItemExtensionPoint<Plugin>(