feat: 初始化 Halo 暗色模式插件
- Halo Plugin 后端(Java/Gradle),含 DarkModePlugin 主类和测试 - Vue 3 + TypeScript 前端 UI,包含主题切换组件和设置页面 - 暗色模式 CSS 变量和覆盖样式(布局/编辑器/表单/滚动条等) - 设计文档和调查文档 - Halo 插件/主题开发 Agent Skills Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
# UI Entry & Routes
|
||||
|
||||
The frontend entry file exports a plugin definition using `definePlugin` from `@halo-dev/ui-shared`.
|
||||
|
||||
## Entry File (`ui/src/index.ts`)
|
||||
|
||||
```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)
|
||||
|
||||
```ts
|
||||
{
|
||||
parentName: "Root",
|
||||
route: { /* RouteRecordRaw */ }
|
||||
}
|
||||
```
|
||||
|
||||
### Without parentName (RouteRecordRaw)
|
||||
|
||||
```ts
|
||||
{
|
||||
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
|
||||
|
||||
```ts
|
||||
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`:
|
||||
|
||||
```ts
|
||||
import { IconComputer } from "@halo-dev/components";
|
||||
import { markRaw } from "vue";
|
||||
|
||||
icon: markRaw(IconComputer);
|
||||
```
|
||||
|
||||
## Permissions in Routes
|
||||
|
||||
```ts
|
||||
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.
|
||||
|
||||
```ts
|
||||
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`.
|
||||
Reference in New Issue
Block a user