文章数据列表操作菜单
此扩展点用于扩展文章数据列表的操作菜单项。
定义方式
export default definePlugin({
extensionPoints: {
"post:list-item:operation:create": (
post: Ref<ListedPost>
): OperationItem<ListedPost>[] | Promise<OperationItem<ListedPost>[]> => {
return [
{
priority: 10,
component: markRaw(VDropdownItem),
props: {},
action: (item?: ListedPost) => {
// do something
},
label: "foo",
hidden: false,
permissions: [],
children: [],
},
];
},
},
});
OperationItem
export interface OperationItem<T> {
priority: number; // 排序优先级
component: Raw<Component>; // 菜单项组件
props?: Record<string, unknown>; // 菜单项组件属性
action?: (item?: T) => void; // 菜单项点击事件
label?: string; // 菜单项标题
hidden?: boolean; // 菜单项是否隐藏
permissions?: string[]; // 菜单项 UI 权限
children?: OperationItem<T>[]; // 子菜单项
}
示例
此示例将实现一个操作菜单项,点击后会将文章内容作为文件下载到本地。
import type { ListedPost } from "@halo-dev/api-client";
import { VDropdownItem } from "@halo-dev/components";
import { definePlugin } from "@halo-dev/console-shared";
import axios from "axios";
import { markRaw } from "vue";
export default definePlugin({
extensionPoints: {
"post:list-item:operation:create": () => {
return [
{
priority: 21,
component: markRaw(VDropdownItem),
label: "下载到本地",
visible: true,
permissions: [],
action: async (post: ListedPost) => {
const { data } = await axios.get(
`/apis/api.console.halo.run/v1alpha1/posts/${post.post.metadata.name}/head-content`
);
const blob = new Blob([data.raw], {
type: "text/plain;charset=utf-8",
});
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = `${post.post.spec.title}.${data.rawType}`;
link.click();
},
},
];
},
},
});
类型定义
ListedPost
export interface ListedPost {
categories: Array<{ // 文章的分类集合
apiVersion: "content.halo.run/v1alpha1";
kind: "Category";
metadata: {
annotations: {};
creationTimestamp: string;
labels: {};
name: string; // 分类的唯一标识
version: number;
};
spec: {
children: Array<string>; // 子分类
cover: string; // 分类封面图
description: string; // 分类描述
displayName: string; // 分类名称
priority: number; // 分类优先级
slug: string; // 分类别名
template: string; // 分类渲染模板
};
status: {
permalink: string; // 分类的永久链接
postCount: number; // 分类下的文章总数
visiblePostCount: number; // 分类下可见的文章总数
};
}>;
contributors: Array<{ // 文章的贡献者集合
avatar: string; // 贡献者头像
displayName: string; // 贡献者名称
name: string; // 贡献者唯一标识
}>;
owner: { // 文章的作者信息
avatar: string; // 作者头像
displayName: string; // 作者名称
name: string; // 作者唯一标识
};
post: { // 文章信息
apiVersion: "content.halo.run/v1alpha1";
kind: "Post";
metadata: {
annotations: {};
creationTimestamp: string;
labels: {};
name: string; // 文章的唯一标识
version: number;
};
spec: {
allowComment: boolean; // 是否允许评论
baseSnapshot: string; // 内容基础快照
categories: Array<string>; // 文章所属分类
cover: string; // 文章封面图
deleted: boolean; // 是否已删除
excerpt: { // 文章摘要
autoGenerate: boolean; // 是否自动生成
raw: string; // 摘要内容
};
headSnapshot: string; // 内容最新快照
htmlMetas: Array<{}>;
owner: string; // 文章作者的唯一标识
pinned: boolean; // 是否置顶
priority: number; // 文章优先级
publish: boolean; // 是否发布
publishTime: string; // 发布时间
releaseSnapshot: string; // 已发布的内容快照
slug: string; // 文章别名
tags: Array<string>; // 文章所属标签
template: string; // 文章渲染模板
title: string; // 文章标题
visible: string; // 文章可见性
};
status: {
commentsCount: number; // 文章评论总数
conditions: Array<{
lastTransitionTime: string;
message: string;
reason: string;
status: string;
type: string;
}>;
contributors: Array<string>;
excerpt: string; // 最终的文章摘要,根据是否自动生成计算
inProgress: boolean; // 是否有未发布的内容
lastModifyTime: string; // 文章最后修改时间
permalink: string; // 文章的永久链接
phase: string;
};
};
stats: {
approvedComment: number; // 已审核的评论数
totalComment: number; // 评论总数
upvote: number; // 点赞数
visit: number; // 访问数
};
tags: Array<{ // 文章的标签集合
apiVersion: "content.halo.run/v1alpha1";
kind: "Tag";
metadata: {
annotations: {};
creationTimestamp: string;
labels: {};
name: string; // 标签的唯一标识
version: number;
};
spec: {
color: string; // 标签颜色
cover: string; // 标签封面图
displayName: string; // 标签名称
slug: string; // 标签别名
};
status: {
permalink: string; // 标签的永久链接
postCount: number; // 标签下的文章总数
visiblePostCount: number; // 标签下可见的文章总数
};
}>;
}