diff --git a/frontend/types/extensionType.ts b/frontend/Requirements/extensionRequirement.ts similarity index 95% rename from frontend/types/extensionType.ts rename to frontend/Requirements/extensionRequirement.ts index 3f2a3ae..9092c56 100644 --- a/frontend/types/extensionType.ts +++ b/frontend/Requirements/extensionRequirement.ts @@ -8,7 +8,10 @@ * - component: 可选的组件函数,接受任意参数并返回一个 React 组件。 * - text: 可选的文本生成函数,接受任意参数并返回一个字符串。 */ -export interface ExtensionType { + + +export class ExtensionProps { + /** 可选的操作函数,接受任意参数并返回 void */ action?: (...args: any[]) => void; @@ -18,3 +21,5 @@ export interface ExtensionType { /** 可选的文本生成函数,接受任意参数并返回一个字符串 */ text?: (...args: any[]) => string; } + + diff --git a/frontend/Requirements/generalRequirement.ts b/frontend/Requirements/generalRequirement.ts new file mode 100644 index 0000000..3a36913 --- /dev/null +++ b/frontend/Requirements/generalRequirement.ts @@ -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; diff --git a/frontend/types/pluginType.ts b/frontend/Requirements/pluginRequirement.ts similarity index 55% rename from frontend/types/pluginType.ts rename to frontend/Requirements/pluginRequirement.ts index c64e537..c8ad372 100644 --- a/frontend/types/pluginType.ts +++ b/frontend/Requirements/pluginRequirement.ts @@ -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 { name: string; // 插件名称 version: string; // 插件版本 @@ -16,10 +21,6 @@ export interface PluginConfig { icon?: string; // 插件图标URL(可选) managePath?: string; // 插件管理页面路径(可选) configuration?: PluginConfiguration; // 插件配置 - dependencies?: { - plugins?: string[]; // 依赖的插件列表(可选) - themes?: string[]; // 依赖的主题列表(可选) - }; hooks?: { onInstall?: (context: any) => {}; // 安装时调用的钩子(可选) onUninstall?: (context: any) => {}; // 卸载时调用的钩子(可选) @@ -38,11 +39,32 @@ export interface PluginConfig { * 该接口定义了插件的配置类型及其属性。 */ export interface PluginConfiguration { - type: string; // 配置类型 - properties: Record; + 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; // 文本生成函数(可选) } \ No newline at end of file diff --git a/frontend/types/templateType.ts b/frontend/Requirements/templateTypeRequirement.ts similarity index 88% rename from frontend/types/templateType.ts rename to frontend/Requirements/templateTypeRequirement.ts index 9c71c2e..750dba1 100644 --- a/frontend/types/templateType.ts +++ b/frontend/Requirements/templateTypeRequirement.ts @@ -5,7 +5,7 @@ * 该接口定义了模板的基本配置,包括依赖项、钩子和页面渲染函数。 */ import React from "react"; -import { ExtensionType } from "types/extensionType"; +import { ExtensionProps } from "types/extensionRequirement"; export interface TemplateConfig { /** @@ -22,7 +22,7 @@ export interface TemplateConfig { extensions?: Record; /** diff --git a/frontend/types/themeType.ts b/frontend/Requirements/themeTypeRequirement.ts similarity index 92% rename from frontend/types/themeType.ts rename to frontend/Requirements/themeTypeRequirement.ts index 5a661e4..efb9bb6 100644 --- a/frontend/types/themeType.ts +++ b/frontend/Requirements/themeTypeRequirement.ts @@ -8,6 +8,7 @@ * 主题配置接口 * 定义主题的基本信息、模板、全局配置、依赖、钩子和路由。 */ +import { SerializeType } from "./generalRequirement"; export interface ThemeConfig { name: string; // 主题的名称 displayName: string; // 主题的显示名称 @@ -23,10 +24,9 @@ export interface ThemeConfig { }; /** 主题配置文件 */ settingsSchema: Record; /** 依赖 */ dependencies?: { diff --git a/frontend/hooks/createServiceContext.tsx b/frontend/hooks/createServiceContext.tsx new file mode 100644 index 0000000..0948c5c --- /dev/null +++ b/frontend/hooks/createServiceContext.tsx @@ -0,0 +1,55 @@ +// File path: /hooks/createServiceContext.tsx + +import { createContext, ReactNode, useContext } from "react"; + +/** + * 创建一个服务上下文,用于提供和使用服务实例。 + * + * @param name - 服务的名称,用于错误提示。 + * @param getInstance - 一个函数,用于获取服务实例。 + * @returns 返回一个包含 Provider 组件和 useService 钩子的对象。 + */ +interface ServiceContextResult { + Provider: React.FC<{ children: ReactNode }>; // 提供服务实例的组件 + useService: () => T; // 获取服务实例的钩子 +} + +/** + * 创建服务上下文的函数。 + * + * @param name - 服务的名称,用于错误提示。 + * @param getInstance - 获取服务实例的函数。 + * @returns 包含 Provider 组件和 useService 钩子的对象。 + */ +export function createServiceContext( + name: string, + getInstance: () => T +): ServiceContextResult { + // 创建一个上下文,初始值为 undefined。 + const ServiceContext = createContext(undefined); + + // Provider 组件,用于提供服务实例给子组件 + const Provider = ({ children }: { children: ReactNode }) => { + const service = getInstance(); + + return ( + + {children} + + ); + }; + + // 获取服务实例的钩子 + 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, + }; +} diff --git a/frontend/hooks/extensionService.tsx b/frontend/hooks/extensionService.tsx new file mode 100644 index 0000000..c6a09f8 --- /dev/null +++ b/frontend/hooks/extensionService.tsx @@ -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(undefined); + +/** + * 扩展提供者组件,用于提供扩展服务的上下文。 + * + * @param children - 要渲染的子组件。 + */ +export function ExtensionProvider({ children }: { children: ReactNode }) { + const extensionService = ExtensionService.getInstance(); // 获取扩展服务实例 + + return ( + + {children} + + ) +} + +/** + * 自定义 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; // 返回扩展服务实例 +} \ No newline at end of file diff --git a/frontend/hooks/themeContext.tsx b/frontend/hooks/themeContext.tsx index 004567f..c045f9d 100644 --- a/frontend/hooks/themeContext.tsx +++ b/frontend/hooks/themeContext.tsx @@ -1,9 +1,16 @@ -// service/theme/themeContext.tsx +// File path: /hooks/themeContext.tsx + import { createContext, useContext, ReactNode } from 'react'; import { ThemeService } from 'service/themeService'; const ThemeContext = createContext(undefined); +/** + * ThemeProvider 组件用于提供主题上下文给其子组件。 + * 它使用 ThemeService 的单例实例来管理主题相关的状态和功能。 + * + * @param children - 要渲染的子组件。 + */ export function ThemeProvider({ children }: { children: ReactNode }) { const themeService = ThemeService.getInstance(); @@ -14,6 +21,12 @@ export function ThemeProvider({ children }: { children: ReactNode }) { ); } +/** + * useTheme 钩子用于访问主题上下文。 + * + * @returns ThemeService - 返回主题服务的实例。 + * @throws Error - 如果在 ThemeProvider 之外使用,将抛出错误。 + */ export function useTheme(): ThemeService { const context = useContext(ThemeContext); if (context === undefined) { diff --git a/frontend/service/extensionService.ts b/frontend/service/extensionService.ts index e060e6e..ff49444 100644 --- a/frontend/service/extensionService.ts +++ b/frontend/service/extensionService.ts @@ -4,38 +4,42 @@ * ExtensionManage 是一个单例类,用于管理扩展的实例。 * 提供注册、触发和移除插件扩展的功能。 */ -import { ExtensionType } from "types/extensionType"; +import { ExtensionProps } from "types/extensionRequirement"; import React from "react"; +import { PluginConfiguration } from "types/pluginRequirement"; -class ExtensionManage { +export class ExtensionService { /** 存储扩展的映射,键为扩展名称,值为插件名称和扩展的集合 */ - private extensions: Map> = new Map(); + private extensions: Map> = new Map(); + private configuration: Map = new Map(); /** ExtensionManage 的唯一实例 */ - private static instance: ExtensionManage; + private static instance: ExtensionService; /** 私有构造函数,防止外部实例化 */ - private constructor() {} + private constructor() { } /** * 获取 ExtensionManage 的唯一实例。 * @returns {ExtensionManage} 返回 ExtensionManage 的唯一实例。 */ - public static getInstance(): ExtensionManage { + public static getInstance(): ExtensionService { if (!this.instance) { - this.instance = new ExtensionManage(); + this.instance = new ExtensionService(); } 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(); + this.configuration.has(extensionName) || this.configuration.set(pluginName, pluginConfiguration); + handlers.add({ pluginName, extension }); this.extensions.set(extensionName, handlers); } /** 执行扩展方法 */ - private executeExtensionMethod(extensionName: string, method: keyof ExtensionType, ...args: any[]): Set { + private executeExtensionMethod(extensionName: string, method: keyof ExtensionProps, ...args: any[]): Set { const result = new Set(); const handlers = this.extensions.get(extensionName); @@ -80,5 +84,11 @@ class ExtensionManage { ); this.extensions.set(extensionName, newHandlers); }); + this.configuration.delete(pluginName); + } + + //获取指定配置文件 + getConfiguration(pluginName: string): PluginConfiguration | undefined { + return this.configuration.get(pluginName); } } diff --git a/frontend/service/pluginService.ts b/frontend/service/pluginService.ts index 742fb84..6ea7f9e 100644 --- a/frontend/service/pluginService.ts +++ b/frontend/service/pluginService.ts @@ -1,24 +1,34 @@ -import { PluginConfig ,PluginType ,PluginConfiguration} from "types/pluginType"; - +// File path: /service/pluginService.ts +/** + * 插件服务类,采用单例模式管理插件组件。 + * 提供获取插件实例的方法,并缓存插件组件信息。 + */ +import { PluginConfiguration } from "types/pluginRequirement"; export class PluginService { - private static pluginInstance: PluginService | null = null; // 单例实例 - private pluginComponents: Map> = new Map(); // 插件组件缓存 - private constructor (){}; + /** 单例实例 */ + private static pluginInstance: PluginService | null = null; + /** 插件组件缓存 */ + private pluginComponents: Map> = new Map(); + /** + * 私有构造函数,防止外部实例化。 + */ + private constructor() {}; + + /** + * 获取插件服务的单例实例。 + * @returns {PluginService} 插件服务实例 + */ public static getInstance(): PluginService { if (!this.pluginInstance) { this.pluginInstance = new PluginService(); } return this.pluginInstance; } - - -} \ No newline at end of file +} diff --git a/frontend/service/themeService.ts b/frontend/service/themeService.ts index e684b2f..e1f0ec2 100644 --- a/frontend/service/themeService.ts +++ b/frontend/service/themeService.ts @@ -1,5 +1,5 @@ // service/theme/themeService.ts -import type { ThemeConfig } from 'types/themeType'; +import type { ThemeConfig } from 'types/themeTypeRequirement'; export class ThemeService { private static themeInstance: ThemeService; // 单例实例 diff --git a/frontend/theme/default/theme.config.ts b/frontend/theme/default/theme.config.ts index d8be258..0486865 100644 --- a/frontend/theme/default/theme.config.ts +++ b/frontend/theme/default/theme.config.ts @@ -1,4 +1,4 @@ -import { ThemeConfig } from "types/themeType"; +import { ThemeConfig } from "types/themeTypeRequirement"; export const themeConfig: ThemeConfig = { name: 'default', diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 7d099cd..d7c93bf 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -24,7 +24,7 @@ "baseUrl": ".", "paths": { "theme/*":["./theme/*"], - "types/*":["./types/*"], + "types/*":["Requirements/*"], "service/*":["./service/*"], "hooks/*":["./hooks/*"], },