实现了对拓展的定义和拓展服务
This commit is contained in:
parent
2b44435c2a
commit
1385251318
@ -8,7 +8,10 @@
|
|||||||
* - component: 可选的组件函数,接受任意参数并返回一个 React 组件。
|
* - component: 可选的组件函数,接受任意参数并返回一个 React 组件。
|
||||||
* - text: 可选的文本生成函数,接受任意参数并返回一个字符串。
|
* - text: 可选的文本生成函数,接受任意参数并返回一个字符串。
|
||||||
*/
|
*/
|
||||||
export interface ExtensionType {
|
|
||||||
|
|
||||||
|
export class ExtensionProps {
|
||||||
|
|
||||||
/** 可选的操作函数,接受任意参数并返回 void */
|
/** 可选的操作函数,接受任意参数并返回 void */
|
||||||
action?: (...args: any[]) => void;
|
action?: (...args: any[]) => void;
|
||||||
|
|
||||||
@ -18,3 +21,5 @@ export interface ExtensionType {
|
|||||||
/** 可选的文本生成函数,接受任意参数并返回一个字符串 */
|
/** 可选的文本生成函数,接受任意参数并返回一个字符串 */
|
||||||
text?: (...args: any[]) => string;
|
text?: (...args: any[]) => string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
frontend/Requirements/generalRequirement.ts
Normal file
12
frontend/Requirements/generalRequirement.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// File path: /d:/data/echoes/frontend/Requirements/generalRequirement.ts
|
||||||
|
/**
|
||||||
|
* 表示可以序列化的类型。
|
||||||
|
* 可以是以下类型之一:
|
||||||
|
* - null
|
||||||
|
* - number
|
||||||
|
* - string
|
||||||
|
* - boolean
|
||||||
|
* - 对象,键为字符串,值为可序列化类型
|
||||||
|
* - 数组,元素为可序列化类型
|
||||||
|
*/
|
||||||
|
export type SerializeType = null | number | string | boolean | { [key: string]: SerializeType } | Array<SerializeType>;
|
@ -1,4 +1,4 @@
|
|||||||
// File path: types/pluginType.ts
|
// File path: ../Requirements/pluginRequirement.ts
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 插件配置接口
|
* 插件配置接口
|
||||||
@ -6,6 +6,11 @@
|
|||||||
* 该接口定义了插件的基本配置,包括插件的名称、版本、描述、作者等信息。
|
* 该接口定义了插件的基本配置,包括插件的名称、版本、描述、作者等信息。
|
||||||
* 还包括插件的生命周期钩子和依赖项的配置。
|
* 还包括插件的生命周期钩子和依赖项的配置。
|
||||||
*/
|
*/
|
||||||
|
import { SerializeType } from "./generalRequirement";
|
||||||
|
import { ExtensionProps } from "types/extensionRequirement";
|
||||||
|
import { useExtention } from "hooks/extensionService";
|
||||||
|
import { ExtensionService } from "service/extensionService";
|
||||||
|
|
||||||
export interface PluginConfig {
|
export interface PluginConfig {
|
||||||
name: string; // 插件名称
|
name: string; // 插件名称
|
||||||
version: string; // 插件版本
|
version: string; // 插件版本
|
||||||
@ -16,10 +21,6 @@ export interface PluginConfig {
|
|||||||
icon?: string; // 插件图标URL(可选)
|
icon?: string; // 插件图标URL(可选)
|
||||||
managePath?: string; // 插件管理页面路径(可选)
|
managePath?: string; // 插件管理页面路径(可选)
|
||||||
configuration?: PluginConfiguration; // 插件配置
|
configuration?: PluginConfiguration; // 插件配置
|
||||||
dependencies?: {
|
|
||||||
plugins?: string[]; // 依赖的插件列表(可选)
|
|
||||||
themes?: string[]; // 依赖的主题列表(可选)
|
|
||||||
};
|
|
||||||
hooks?: {
|
hooks?: {
|
||||||
onInstall?: (context: any) => {}; // 安装时调用的钩子(可选)
|
onInstall?: (context: any) => {}; // 安装时调用的钩子(可选)
|
||||||
onUninstall?: (context: any) => {}; // 卸载时调用的钩子(可选)
|
onUninstall?: (context: any) => {}; // 卸载时调用的钩子(可选)
|
||||||
@ -38,11 +39,32 @@ export interface PluginConfig {
|
|||||||
* 该接口定义了插件的配置类型及其属性。
|
* 该接口定义了插件的配置类型及其属性。
|
||||||
*/
|
*/
|
||||||
export interface PluginConfiguration {
|
export interface PluginConfiguration {
|
||||||
type: string; // 配置类型
|
[key: string]: {
|
||||||
properties: Record<string, {
|
|
||||||
type: string; // 属性类型
|
|
||||||
title: string; // 属性标题
|
title: string; // 属性标题
|
||||||
description?: string; // 属性描述(可选)
|
description?: string; // 属性描述(可选)
|
||||||
data: any; // 额外数据(可选)
|
data: SerializeType; // 额外数据(可选),支持序列化
|
||||||
}>;
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PluginDependencies {
|
||||||
|
plugins: string[]; // 依赖的插件列表(可选)
|
||||||
|
themes: string[]; // 依赖的主题列表(可选)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件属性接口
|
||||||
|
*
|
||||||
|
* 该接口定义了插件的属性和行为。
|
||||||
|
*/
|
||||||
|
export class usePluginProps implements ExtensionProps {
|
||||||
|
private extensionService: ExtensionService = useExtention();
|
||||||
|
private dependencies: PluginDependencies;
|
||||||
|
|
||||||
|
constructor(dependencies: PluginDependencies) {
|
||||||
|
this.dependencies = dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
action?: ((...args: any[]) => void); // 动作函数(可选)
|
||||||
|
component?: (...args: any[]) => React.FC; // 组件函数(可选)
|
||||||
|
text?: (...args: any[]) => string; // 文本生成函数(可选)
|
||||||
}
|
}
|
@ -5,7 +5,7 @@
|
|||||||
* 该接口定义了模板的基本配置,包括依赖项、钩子和页面渲染函数。
|
* 该接口定义了模板的基本配置,包括依赖项、钩子和页面渲染函数。
|
||||||
*/
|
*/
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { ExtensionType } from "types/extensionType";
|
import { ExtensionProps } from "types/extensionRequirement";
|
||||||
|
|
||||||
export interface TemplateConfig {
|
export interface TemplateConfig {
|
||||||
/**
|
/**
|
||||||
@ -22,7 +22,7 @@ export interface TemplateConfig {
|
|||||||
|
|
||||||
extensions?: Record<string, {
|
extensions?: Record<string, {
|
||||||
description?: string;
|
description?: string;
|
||||||
extension: ExtensionType;
|
extension: ExtensionProps;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
/**
|
/**
|
@ -8,6 +8,7 @@
|
|||||||
* 主题配置接口
|
* 主题配置接口
|
||||||
* 定义主题的基本信息、模板、全局配置、依赖、钩子和路由。
|
* 定义主题的基本信息、模板、全局配置、依赖、钩子和路由。
|
||||||
*/
|
*/
|
||||||
|
import { SerializeType } from "./generalRequirement";
|
||||||
export interface ThemeConfig {
|
export interface ThemeConfig {
|
||||||
name: string; // 主题的名称
|
name: string; // 主题的名称
|
||||||
displayName: string; // 主题的显示名称
|
displayName: string; // 主题的显示名称
|
||||||
@ -23,10 +24,9 @@ export interface ThemeConfig {
|
|||||||
};
|
};
|
||||||
/** 主题配置文件 */
|
/** 主题配置文件 */
|
||||||
settingsSchema: Record<string, {
|
settingsSchema: Record<string, {
|
||||||
type: string; // 属性的数据类型
|
name: string; // 属性的名称
|
||||||
title: string; // 属性的标题
|
|
||||||
description?: string; // 属性的描述信息
|
description?: string; // 属性的描述信息
|
||||||
data?: any; // 属性的默认数据
|
data: SerializeType; // 属性的默认数据
|
||||||
}>;
|
}>;
|
||||||
/** 依赖 */
|
/** 依赖 */
|
||||||
dependencies?: {
|
dependencies?: {
|
55
frontend/hooks/createServiceContext.tsx
Normal file
55
frontend/hooks/createServiceContext.tsx
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// File path: /hooks/createServiceContext.tsx
|
||||||
|
|
||||||
|
import { createContext, ReactNode, useContext } from "react";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建一个服务上下文,用于提供和使用服务实例。
|
||||||
|
*
|
||||||
|
* @param name - 服务的名称,用于错误提示。
|
||||||
|
* @param getInstance - 一个函数,用于获取服务实例。
|
||||||
|
* @returns 返回一个包含 Provider 组件和 useService 钩子的对象。
|
||||||
|
*/
|
||||||
|
interface ServiceContextResult<T> {
|
||||||
|
Provider: React.FC<{ children: ReactNode }>; // 提供服务实例的组件
|
||||||
|
useService: () => T; // 获取服务实例的钩子
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建服务上下文的函数。
|
||||||
|
*
|
||||||
|
* @param name - 服务的名称,用于错误提示。
|
||||||
|
* @param getInstance - 获取服务实例的函数。
|
||||||
|
* @returns 包含 Provider 组件和 useService 钩子的对象。
|
||||||
|
*/
|
||||||
|
export function createServiceContext<T>(
|
||||||
|
name: string,
|
||||||
|
getInstance: () => T
|
||||||
|
): ServiceContextResult<T> {
|
||||||
|
// 创建一个上下文,初始值为 undefined。
|
||||||
|
const ServiceContext = createContext<T | undefined>(undefined);
|
||||||
|
|
||||||
|
// Provider 组件,用于提供服务实例给子组件
|
||||||
|
const Provider = ({ children }: { children: ReactNode }) => {
|
||||||
|
const service = getInstance();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ServiceContext.Provider value={service}>
|
||||||
|
{children}
|
||||||
|
</ServiceContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取服务实例的钩子
|
||||||
|
const useService = (): T => {
|
||||||
|
const context = useContext(ServiceContext);
|
||||||
|
if (context === undefined) {
|
||||||
|
throw new Error(`use${name} must be used within a ${name}Provider`);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
Provider,
|
||||||
|
useService,
|
||||||
|
};
|
||||||
|
}
|
41
frontend/hooks/extensionService.tsx
Normal file
41
frontend/hooks/extensionService.tsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// File path: /d:/data/echoes/frontend/hooks/extensionService.tsx
|
||||||
|
/**
|
||||||
|
* 扩展服务上下文提供者和自定义 Hook。
|
||||||
|
*
|
||||||
|
* 该文件包含扩展服务的上下文提供者组件和用于访问该上下文的自定义 Hook。
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { createContext, useContext, ReactNode } from 'react';
|
||||||
|
import { ExtensionService } from 'service/extensionService';
|
||||||
|
|
||||||
|
// 创建扩展服务上下文
|
||||||
|
const ExtensionContext = createContext<ExtensionService | undefined>(undefined);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扩展提供者组件,用于提供扩展服务的上下文。
|
||||||
|
*
|
||||||
|
* @param children - 要渲染的子组件。
|
||||||
|
*/
|
||||||
|
export function ExtensionProvider({ children }: { children: ReactNode }) {
|
||||||
|
const extensionService = ExtensionService.getInstance(); // 获取扩展服务实例
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ExtensionContext.Provider value={extensionService}>
|
||||||
|
{children}
|
||||||
|
</ExtensionContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义 Hook,用于访问扩展服务上下文。
|
||||||
|
*
|
||||||
|
* @returns {ExtensionService} - 返回扩展服务实例。
|
||||||
|
* @throws {Error} - 如果在未被 ExtensionProvider 包裹的组件中调用,将抛出错误。
|
||||||
|
*/
|
||||||
|
export function useExtention(): ExtensionService {
|
||||||
|
const context = useContext(ExtensionContext); // 获取扩展服务上下文
|
||||||
|
if (context === undefined) {
|
||||||
|
throw new Error('useTheme must be used within a ThemeProvider'); // 抛出错误
|
||||||
|
}
|
||||||
|
return context; // 返回扩展服务实例
|
||||||
|
}
|
@ -1,9 +1,16 @@
|
|||||||
// service/theme/themeContext.tsx
|
// File path: /hooks/themeContext.tsx
|
||||||
|
|
||||||
import { createContext, useContext, ReactNode } from 'react';
|
import { createContext, useContext, ReactNode } from 'react';
|
||||||
import { ThemeService } from 'service/themeService';
|
import { ThemeService } from 'service/themeService';
|
||||||
|
|
||||||
const ThemeContext = createContext<ThemeService | undefined>(undefined);
|
const ThemeContext = createContext<ThemeService | undefined>(undefined);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ThemeProvider 组件用于提供主题上下文给其子组件。
|
||||||
|
* 它使用 ThemeService 的单例实例来管理主题相关的状态和功能。
|
||||||
|
*
|
||||||
|
* @param children - 要渲染的子组件。
|
||||||
|
*/
|
||||||
export function ThemeProvider({ children }: { children: ReactNode }) {
|
export function ThemeProvider({ children }: { children: ReactNode }) {
|
||||||
const themeService = ThemeService.getInstance();
|
const themeService = ThemeService.getInstance();
|
||||||
|
|
||||||
@ -14,6 +21,12 @@ export function ThemeProvider({ children }: { children: ReactNode }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* useTheme 钩子用于访问主题上下文。
|
||||||
|
*
|
||||||
|
* @returns ThemeService - 返回主题服务的实例。
|
||||||
|
* @throws Error - 如果在 ThemeProvider 之外使用,将抛出错误。
|
||||||
|
*/
|
||||||
export function useTheme(): ThemeService {
|
export function useTheme(): ThemeService {
|
||||||
const context = useContext(ThemeContext);
|
const context = useContext(ThemeContext);
|
||||||
if (context === undefined) {
|
if (context === undefined) {
|
||||||
|
@ -4,38 +4,42 @@
|
|||||||
* ExtensionManage 是一个单例类,用于管理扩展的实例。
|
* ExtensionManage 是一个单例类,用于管理扩展的实例。
|
||||||
* 提供注册、触发和移除插件扩展的功能。
|
* 提供注册、触发和移除插件扩展的功能。
|
||||||
*/
|
*/
|
||||||
import { ExtensionType } from "types/extensionType";
|
import { ExtensionProps } from "types/extensionRequirement";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { PluginConfiguration } from "types/pluginRequirement";
|
||||||
|
|
||||||
class ExtensionManage {
|
export class ExtensionService {
|
||||||
/** 存储扩展的映射,键为扩展名称,值为插件名称和扩展的集合 */
|
/** 存储扩展的映射,键为扩展名称,值为插件名称和扩展的集合 */
|
||||||
private extensions: Map<string, Set<{ pluginName: string; extension: ExtensionType }>> = new Map();
|
private extensions: Map<string, Set<{ pluginName: string; extension: ExtensionProps }>> = new Map();
|
||||||
|
private configuration: Map<string, PluginConfiguration> = new Map();
|
||||||
/** ExtensionManage 的唯一实例 */
|
/** ExtensionManage 的唯一实例 */
|
||||||
private static instance: ExtensionManage;
|
private static instance: ExtensionService;
|
||||||
|
|
||||||
/** 私有构造函数,防止外部实例化 */
|
/** 私有构造函数,防止外部实例化 */
|
||||||
private constructor() {}
|
private constructor() { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 ExtensionManage 的唯一实例。
|
* 获取 ExtensionManage 的唯一实例。
|
||||||
* @returns {ExtensionManage} 返回 ExtensionManage 的唯一实例。
|
* @returns {ExtensionManage} 返回 ExtensionManage 的唯一实例。
|
||||||
*/
|
*/
|
||||||
public static getInstance(): ExtensionManage {
|
public static getInstance(): ExtensionService {
|
||||||
if (!this.instance) {
|
if (!this.instance) {
|
||||||
this.instance = new ExtensionManage();
|
this.instance = new ExtensionService();
|
||||||
}
|
}
|
||||||
return this.instance;
|
return this.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 注册扩展 */
|
/** 注册扩展 */
|
||||||
private register(extensionName: string, pluginName: string, extension: ExtensionType) {
|
private register(extensionName: string, pluginName: string, extension: ExtensionProps, pluginConfiguration: PluginConfiguration) {
|
||||||
const handlers = this.extensions.get(extensionName) || new Set();
|
const handlers = this.extensions.get(extensionName) || new Set();
|
||||||
|
this.configuration.has(extensionName) || this.configuration.set(pluginName, pluginConfiguration);
|
||||||
|
|
||||||
handlers.add({ pluginName, extension });
|
handlers.add({ pluginName, extension });
|
||||||
this.extensions.set(extensionName, handlers);
|
this.extensions.set(extensionName, handlers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 执行扩展方法 */
|
/** 执行扩展方法 */
|
||||||
private executeExtensionMethod<T>(extensionName: string, method: keyof ExtensionType, ...args: any[]): Set<T> {
|
private executeExtensionMethod<T>(extensionName: string, method: keyof ExtensionProps, ...args: any[]): Set<T> {
|
||||||
const result = new Set<T>();
|
const result = new Set<T>();
|
||||||
const handlers = this.extensions.get(extensionName);
|
const handlers = this.extensions.get(extensionName);
|
||||||
|
|
||||||
@ -80,5 +84,11 @@ class ExtensionManage {
|
|||||||
);
|
);
|
||||||
this.extensions.set(extensionName, newHandlers);
|
this.extensions.set(extensionName, newHandlers);
|
||||||
});
|
});
|
||||||
|
this.configuration.delete(pluginName);
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取指定配置文件
|
||||||
|
getConfiguration(pluginName: string): PluginConfiguration | undefined {
|
||||||
|
return this.configuration.get(pluginName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,34 @@
|
|||||||
import { PluginConfig ,PluginType ,PluginConfiguration} from "types/pluginType";
|
// File path: /service/pluginService.ts
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件服务类,采用单例模式管理插件组件。
|
||||||
|
* 提供获取插件实例的方法,并缓存插件组件信息。
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { PluginConfiguration } from "types/pluginRequirement";
|
||||||
export class PluginService {
|
export class PluginService {
|
||||||
private static pluginInstance: PluginService | null = null; // 单例实例
|
/** 单例实例 */
|
||||||
private pluginComponents: Map<PluginType, Set<{
|
private static pluginInstance: PluginService | null = null;
|
||||||
name:string,
|
/** 插件组件缓存 */
|
||||||
configuration?:PluginConfiguration,
|
private pluginComponents: Map<string, Set<{
|
||||||
managePath?: string,
|
name: string, // 插件名称
|
||||||
|
configuration?: PluginConfiguration, // 插件配置
|
||||||
|
managePath?: string, // 管理路径
|
||||||
}>> = new Map(); // 插件组件缓存
|
}>> = new Map();
|
||||||
private constructor (){};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 私有构造函数,防止外部实例化。
|
||||||
|
*/
|
||||||
|
private constructor() {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取插件服务的单例实例。
|
||||||
|
* @returns {PluginService} 插件服务实例
|
||||||
|
*/
|
||||||
public static getInstance(): PluginService {
|
public static getInstance(): PluginService {
|
||||||
if (!this.pluginInstance) {
|
if (!this.pluginInstance) {
|
||||||
this.pluginInstance = new PluginService();
|
this.pluginInstance = new PluginService();
|
||||||
}
|
}
|
||||||
return this.pluginInstance;
|
return this.pluginInstance;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// service/theme/themeService.ts
|
// service/theme/themeService.ts
|
||||||
import type { ThemeConfig } from 'types/themeType';
|
import type { ThemeConfig } from 'types/themeTypeRequirement';
|
||||||
|
|
||||||
export class ThemeService {
|
export class ThemeService {
|
||||||
private static themeInstance: ThemeService; // 单例实例
|
private static themeInstance: ThemeService; // 单例实例
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ThemeConfig } from "types/themeType";
|
import { ThemeConfig } from "types/themeTypeRequirement";
|
||||||
|
|
||||||
export const themeConfig: ThemeConfig = {
|
export const themeConfig: ThemeConfig = {
|
||||||
name: 'default',
|
name: 'default',
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"theme/*":["./theme/*"],
|
"theme/*":["./theme/*"],
|
||||||
"types/*":["./types/*"],
|
"types/*":["Requirements/*"],
|
||||||
"service/*":["./service/*"],
|
"service/*":["./service/*"],
|
||||||
"hooks/*":["./hooks/*"],
|
"hooks/*":["./hooks/*"],
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user