edbf78f236
- Halo Plugin 后端(Java/Gradle),含 DarkModePlugin 主类和测试 - Vue 3 + TypeScript 前端 UI,包含主题切换组件和设置页面 - 暗色模式 CSS 变量和覆盖样式(布局/编辑器/表单/滚动条等) - 设计文档和调查文档 - Halo 插件/主题开发 Agent Skills Co-Authored-By: Claude <noreply@anthropic.com>
4.1 KiB
4.1 KiB
UI Entry & Routes
The frontend entry file exports a plugin definition using definePlugin from @halo-dev/ui-shared.
Entry File (ui/src/index.ts)
import { definePlugin } from "@halo-dev/ui-shared";
import HomeView from "./views/HomeView.vue";
import { IconComputer } from "@halo-dev/components";
import { markRaw } from "vue";
export default definePlugin({
components: {
// Global component registration
// "MyComponent": MyComponent
},
routes: [
// Console routes
{
parentName: "Root",
route: {
path: "/my-plugin",
name: "MyPluginHome",
component: HomeView,
meta: {
title: "My Plugin",
permissions: [],
menu: {
name: "My Plugin",
group: "tool", // dashboard | content | interface | system | tool
icon: markRaw(IconComputer),
priority: 40,
},
},
},
},
],
ucRoutes: [
// UC (User Center) routes
{
parentName: "Root",
route: {
path: "/uc-my-plugin",
name: "MyPluginUCHome",
component: HomeView,
meta: {
permissions: [],
menu: {
name: "My Plugin",
priority: 40,
},
},
},
},
],
extensionPoints: {
// UI extension point implementations
},
formkit: {
inputs: {
// Custom FormKit inputs (Halo 2.25+)
},
},
});
Route Definition
With parentName (RouteRecordAppend)
{
parentName: "Root",
route: { /* RouteRecordRaw */ }
}
Without parentName (RouteRecordRaw)
{
path: "/standalone",
name: "StandalonePage",
component: MyView
}
Console Parent Routes
| parentName | Section |
|---|---|
Root |
Top level |
AttachmentsRoot |
Attachment management |
CommentsRoot |
Comments |
SinglePagesRoot |
Single pages |
PostsRoot |
Posts |
MenusRoot |
Menus |
ThemeRoot |
Themes |
OverviewRoot |
Overview |
BackupRoot |
Backups |
PluginsRoot |
Plugins |
SettingsRoot |
Settings |
UsersRoot |
Users |
ToolsRoot |
Tools |
UC Parent Routes
| parentName | Section |
|---|---|
PostsRoot |
Posts |
NotificationsRoot |
Notifications |
RouteMeta
interface RouteMeta {
title?: string; // Browser tab title
searchable?: boolean; // Include in Console global search
permissions?: string[]; // Required UI permissions
menu?: {
name: string; // Menu display name
group?: CoreMenuGroupId; // Built-in group or custom group name
icon?: Component; // Vue icon component (use markRaw)
priority: number; // Sort order (lower = higher)
mobile?: boolean; // Show on mobile
};
}
Using markRaw for Icons
Always wrap icon components with markRaw:
import { IconComputer } from "@halo-dev/components";
import { markRaw } from "vue";
icon: markRaw(IconComputer);
Permissions in Routes
meta: {
permissions: ["plugin:my-plugin:person:manage"];
}
The route is hidden if the user lacks any of the listed permissions.
Custom FormKit Inputs
Halo 2.25+ lets plugin UI entries register custom FormKit inputs for use in plugin-provided FormKit Schema.
import { createInput } from "@formkit/vue";
import { definePlugin } from "@halo-dev/ui-shared";
import { defineAsyncComponent } from "vue";
export default definePlugin({
formkit: {
inputs: {
myPluginInput: createInput(
defineAsyncComponent(() => import("./components/MyPluginInput.vue")),
),
},
},
});
Use a plugin-prefixed input name to avoid collisions with Halo built-ins or
earlier-loaded plugins. If the input definition uses @formkit/vue, require
@halo-dev/ui-plugin-bundler-kit@2.25.0+ and set plugin.yaml spec.requires
to >=2.25.0.