From ddbb770923d4edb8ca83bf2a113fffaeef9792dd Mon Sep 17 00:00:00 2001 From: lsy Date: Mon, 11 Nov 2024 13:45:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8E=E7=AB=AF=E6=95=B0=E6=8D=AE=E5=BA=93?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E7=BB=9F=E4=B8=80=E4=BD=BF=E7=94=A8=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E6=9D=A5?= =?UTF-8?q?=E4=BC=A0=E8=BE=93=E9=85=8D=E7=BD=AE=E4=BF=A1=E6=81=AF=EF=BC=8C?= =?UTF-8?q?=E7=BB=99=E5=90=8E=E7=AB=AF=E4=BB=A3=E7=A0=81=E5=8A=A0=E4=B8=8A?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=EF=BC=8C=E5=89=8D=E7=AB=AF=E6=AD=A3=E5=9C=A8?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=8A=A8=E6=80=81=E5=8A=A0=E8=BD=BD=E4=B8=BB?= =?UTF-8?q?=E9=A2=98=E5=92=8C=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/config.rs | 22 ------ backend/src/{ => config}/config.toml | 3 + backend/src/config/mod.rs | 34 +++++++++ backend/src/main.rs | 90 +++++++++++------------ backend/src/sql/mod.rs | 65 +++++++--------- backend/src/sql/postgresql.rs | 34 +++++---- frontend/hooks/plugin/usePluginLoader.ts | 61 +++++++++++++++ frontend/hooks/theme/themeManager.tsx | 33 +++++++++ frontend/hooks/theme/themeSwitch.tsx | 27 +++++++ frontend/hooks/theme/useThemeLoader.ts | 66 +++++++++++++++++ frontend/services/cache-manager.ts | 41 +++++++++++ frontend/services/dependency-checker.ts | 29 ++++++++ frontend/services/performance-monitor.ts | 54 ++++++++++++++ frontend/services/plugin-communication.ts | 39 ++++++++++ frontend/src/main.tsx | 5 +- frontend/src/page/page.tsx | 1 + frontend/types/common.ts | 18 +++++ frontend/types/plugin.ts | 23 ++++++ frontend/types/theme.ts | 20 +++++ 19 files changed, 540 insertions(+), 125 deletions(-) delete mode 100644 backend/src/config.rs rename backend/src/{ => config}/config.toml (80%) create mode 100644 backend/src/config/mod.rs create mode 100644 frontend/hooks/plugin/usePluginLoader.ts create mode 100644 frontend/hooks/theme/themeManager.tsx create mode 100644 frontend/hooks/theme/themeSwitch.tsx create mode 100644 frontend/hooks/theme/useThemeLoader.ts create mode 100644 frontend/services/cache-manager.ts create mode 100644 frontend/services/dependency-checker.ts create mode 100644 frontend/services/performance-monitor.ts create mode 100644 frontend/services/plugin-communication.ts create mode 100644 frontend/types/common.ts create mode 100644 frontend/types/plugin.ts create mode 100644 frontend/types/theme.ts diff --git a/backend/src/config.rs b/backend/src/config.rs deleted file mode 100644 index 23ffd0a..0000000 --- a/backend/src/config.rs +++ /dev/null @@ -1,22 +0,0 @@ -use serde::Deserialize; - -#[derive(Deserialize)] -pub struct Config { - pub info: Info, - pub database: Database, -} - -#[derive(Deserialize)] -pub struct Info { - pub install: bool, -} - -#[derive(Deserialize)] -pub struct Database { - pub db_type : String, - pub address : String, - pub prot : u32, - pub user : String, - pub password : String, - pub db_name : String, -} \ No newline at end of file diff --git a/backend/src/config.toml b/backend/src/config/config.toml similarity index 80% rename from backend/src/config.toml rename to backend/src/config/config.toml index fddd649..b4a293d 100644 --- a/backend/src/config.toml +++ b/backend/src/config/config.toml @@ -1,3 +1,6 @@ +# config/config.toml +# 配置文件 + [info] install = false diff --git a/backend/src/config/mod.rs b/backend/src/config/mod.rs new file mode 100644 index 0000000..454564e --- /dev/null +++ b/backend/src/config/mod.rs @@ -0,0 +1,34 @@ +// config/mod.rs +/* + 配置文件结构和操作 + */ +use std::fs; +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct Config { + pub info: Info, + pub database: Database, +} + +#[derive(Deserialize)] +pub struct Info { + pub install: bool, +} + +#[derive(Deserialize)] +pub struct Database { + pub db_type: String, + pub address: String, + pub prot: u32, + pub user: String, + pub password: String, + pub db_name: String, +} + +impl Config { + /// 读取配置文件 + pub fn read(path: &str) -> Result> { + Ok(toml::from_str(&fs::read_to_string(path)?)?) + } +} diff --git a/backend/src/main.rs b/backend/src/main.rs index 593520b..b8163af 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -1,68 +1,66 @@ // main.rs -mod sql; mod config; -use rocket::{ get, launch, routes}; -use rocket::serde::json::Json; // Added import for Json -use once_cell::sync::Lazy; -use rocket::http::Status; -use rocket::response::status; -use std::sync::Arc; // Added import for Arc and Mutex -use tokio::sync::Mutex; +mod sql; use crate::sql::Database; +use once_cell::sync::Lazy; +use rocket::{get, http::Status, launch, response::status, routes, serde::json::Json}; +use std::sync::Arc; +use tokio::sync::Mutex; -// 修改全局变量的类型定义 -static GLOBAL_SQL: Lazy>>> = Lazy::new(|| { - Arc::new(Mutex::new(None)) -}); +/* 修改全局变量的类型定义 */ +static DB: Lazy>>> = Lazy::new(|| Arc::new(Mutex::new(None))); -// 修改数据库连接函数 -async fn connect_database() -> Result<(), Box> { - let database = sql::Database::init().await?; - let mut lock = GLOBAL_SQL.lock().await; - *lock = Some(database); +/* 数据库连接函数 */ +async fn init_db(database: config::Database) -> Result<(), Box> { + let database = Database::init(database).await?; + *DB.lock().await = Some(database); Ok(()) } - +/* 获取数据库的引用 */ async fn get_db() -> Result> { - let lock = GLOBAL_SQL.lock().await; - match &*lock { - Some(db) => Ok(db.clone()), - None => Err("Database not initialized".into()) - } + DB.lock() + .await + .clone() + .ok_or_else(|| "Database not initialized".into()) } - - +/* 用于测试数据库 */ #[get("/sql")] -async fn ssql() -> Result>>, status::Custom> { +async fn ssql( +) -> Result>>, status::Custom> { let db = get_db().await.map_err(|e| { - eprintln!("Database error: {}", e); - status::Custom(Status::InternalServerError, format!("Database error: {}", e)) + status::Custom( + Status::InternalServerError, + format!("Database error: {}", e), + ) })?; - let query_result = db.get_db() - .query("SELECT * FROM info".to_string()) // 确保这里是正确的表名 + let query_result = db + .get_db() + .query("SELECT * FROM info".to_string()) .await - .map_err(|e| { - eprintln!("Query error: {}", e); - status::Custom(Status::InternalServerError, format!("Query error: {}", e)) - })?; + .map_err(|e| status::Custom(Status::InternalServerError, format!("Query error: {}", e)))?; Ok(Json(query_result)) } - - +/* 安装接口 */ #[get("/install")] async fn install() -> status::Custom { - match connect_database().await { - Ok(_) => status::Custom(Status::Ok, "Database connected successfully".to_string()), - Err(e) => status::Custom(Status::InternalServerError, format!("Failed to connect: {}", e)) - } + get_db() + .await + .map(|_| status::Custom(Status::Ok, "Database connected successfully".into())) + .unwrap_or_else(|e| { + status::Custom( + Status::InternalServerError, + format!("Failed to connect: {}", e), + ) + }) } - - +/* 启动函数 */ #[launch] async fn rocket() -> _ { - connect_database().await.expect("Failed to connect to database"); - rocket::build() - .mount("/api", routes![install,ssql]) -} \ No newline at end of file + let config = config::Config::read("./src/config/config.toml").expect("Failed to read config"); + init_db(config.database) + .await + .expect("Failed to connect to database"); + rocket::build().mount("/api", routes![install, ssql]) +} diff --git a/backend/src/sql/mod.rs b/backend/src/sql/mod.rs index fb37715..f5a9761 100644 --- a/backend/src/sql/mod.rs +++ b/backend/src/sql/mod.rs @@ -1,57 +1,42 @@ -// mod.rs +// sql/mod.rs +/* + 定义了数据库具有的特征和方法 +*/ mod postgresql; -use std::{collections::HashMap, fs}; -use toml; -use crate::config::Config; +use std::collections::HashMap; +use super::config; use async_trait::async_trait; use std::error::Error; use std::sync::Arc; + #[async_trait] -pub trait Databasetrait: Send + Sync { - async fn connect( - address: String, - port: u32, - user: String, - password: String, - dbname: String, - ) -> Result> where Self: Sized; +pub trait DatabaseTrait: Send + Sync { + // 连接数据库 + async fn connect(database: config::Database) -> Result> where Self: Sized; + // 执行查询 async fn query<'a>(&'a self, query: String) -> Result>, Box>; } + #[derive(Clone)] pub struct Database { - pub db: Arc>, + // 数据库实例 + pub db: Arc>, } impl Database { - pub fn get_db(&self) -> &Box { + // 获取当前数据库实例 + pub fn get_db(&self) -> &Box { &self.db } -} + + // 初始化数据库 + pub async fn init(database: config::Database) -> Result> { + let db = match database.db_type.as_str() { + "postgresql" => postgresql::Postgresql::connect(database).await?, + _ => return Err("unknown database type".into()), + }; - - -impl Database { - pub async fn init() -> Result> { - let config_string = fs::read_to_string("./src/config.toml") - .map_err(|e| Box::new(e) as Box)?; - let config: Config = toml::from_str(&config_string) - .map_err(|e| Box::new(e) as Box)?; - - match config.database.db_type.as_str() { - "postgresql" => { - let db = postgresql::Postgresql::connect( - config.database.address, - config.database.prot, - config.database.user, - config.database.password, - config.database.db_name, - ).await?; - Ok(Database { - db: Arc::new(Box::new(db)) - }) - } - _ => Err(anyhow::anyhow!("unknown database type").into()), - } + Ok(Self { db: Arc::new(Box::new(db)) }) } -} \ No newline at end of file +} diff --git a/backend/src/sql/postgresql.rs b/backend/src/sql/postgresql.rs index 2fb5f2d..4721ff6 100644 --- a/backend/src/sql/postgresql.rs +++ b/backend/src/sql/postgresql.rs @@ -1,27 +1,28 @@ +// sql/psotgresql.rs +/* + 为postgresql数据库实现具体的方法 +*/ +use super::DatabaseTrait; +use crate::config; use async_trait::async_trait; -use sqlx::{PgPool, Row,Column}; +use sqlx::{Column, PgPool, Row}; use std::{collections::HashMap, error::Error}; -use super::Databasetrait; #[derive(Clone)] pub struct Postgresql { pool: PgPool, } - - #[async_trait] -impl Databasetrait for Postgresql { - async fn connect( - address: String, - port: u32, - user: String, - password: String, - dbname: String, - ) -> Result> { +impl DatabaseTrait for Postgresql { + async fn connect(database: config::Database) -> Result> { let connection_str = format!( "postgres://{}:{}@{}:{}/{}", - user, password, address, port, dbname + database.user, + database.password, + database.address, + database.prot, + database.db_name ); let pool = PgPool::connect(&connection_str) @@ -30,7 +31,10 @@ impl Databasetrait for Postgresql { Ok(Postgresql { pool }) } - async fn query<'a>(&'a self, query: String) -> Result>, Box> { + async fn query<'a>( + &'a self, + query: String, + ) -> Result>, Box> { let rows = sqlx::query(&query) .fetch_all(&self.pool) .await @@ -49,4 +53,4 @@ impl Databasetrait for Postgresql { Ok(results) } -} \ No newline at end of file +} diff --git a/frontend/hooks/plugin/usePluginLoader.ts b/frontend/hooks/plugin/usePluginLoader.ts new file mode 100644 index 0000000..94e64cd --- /dev/null +++ b/frontend/hooks/plugin/usePluginLoader.ts @@ -0,0 +1,61 @@ +// hooks/usePluginLoader.ts +import { useState, useEffect } from 'react'; +import { DependencyChecker } from '../../services/dependency-checker'; +import { PerformanceMonitor } from '../../services/performance-monitor'; +import { CacheManager } from '../../services/cache-manager'; + +/** + * 插件加载Hook + * @param pluginId 插件ID + * @returns 加载状态和错误信息 + */ +export function usePluginLoader(pluginId: string) { + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const loadPlugin = async () => { + try { + // 检查缓存 + const cached = CacheManager.get(`plugin:${pluginId}`); + if (cached) { + return cached; + } + + // 开始性能监控 + const monitor = PerformanceMonitor.startMonitoring(pluginId); + + // 获取插件配置 + const plugin = await fetch(`/api/admin/plugins/${pluginId}`).then(r => r.json()); + + // 检查依赖 + if (plugin.dependencies) { + const dependenciesOk = await DependencyChecker.checkDependencies(plugin.dependencies); + if (!dependenciesOk) { + throw new Error('依赖检查失败'); + } + } + + // 加载插件 + const component = await import(/* @vite-ignore */plugin.entry); + + // 缓存结果 + CacheManager.set(`plugin:${pluginId}`, component); + + // 结束监控 + monitor.end(); + + return component; + } catch (err) { + setError(err instanceof Error ? err.message : '插件加载失败'); + throw err; + } finally { + setLoading(false); + } + }; + + loadPlugin(); + }, [pluginId]); + + return { loading, error }; +} \ No newline at end of file diff --git a/frontend/hooks/theme/themeManager.tsx b/frontend/hooks/theme/themeManager.tsx new file mode 100644 index 0000000..e49b1ea --- /dev/null +++ b/frontend/hooks/theme/themeManager.tsx @@ -0,0 +1,33 @@ +// components/theme/themeManager.tsx +import React, { useEffect } from 'react'; +import { useThemeLoader } from './useThemeLoader'; + +interface ThemeManagerProps { + themeName: string; + children: React.ReactNode; +} + +export const ThemeManager: React.FC = ({ + themeName, + children +}) => { + const { theme, loading, error } = useThemeLoader(themeName); + + if (loading) { + return
加载主题中...
; + } + + if (error) { + return
主题加载失败: {error}
; + } + + if (!theme) { + return
主题未找到
; + } + + return ( +
+ {children} +
+ ); +}; diff --git a/frontend/hooks/theme/themeSwitch.tsx b/frontend/hooks/theme/themeSwitch.tsx new file mode 100644 index 0000000..4a37451 --- /dev/null +++ b/frontend/hooks/theme/themeSwitch.tsx @@ -0,0 +1,27 @@ +// components/theme/themeSwitch.tsx +import React from 'react'; + +interface ThemeSwitchProps { + currentTheme: string; + availableThemes: string[]; + onThemeChange: (themeName: string) => void; +} + +export const ThemeSwitch: React.FC = ({ + currentTheme, + availableThemes, + onThemeChange +}) => { + return ( + + ); +}; diff --git a/frontend/hooks/theme/useThemeLoader.ts b/frontend/hooks/theme/useThemeLoader.ts new file mode 100644 index 0000000..c28e7e5 --- /dev/null +++ b/frontend/hooks/theme/useThemeLoader.ts @@ -0,0 +1,66 @@ +// hooks/theme/useThemeLoader.ts +import { useState, useEffect } from 'react'; +import { ThemeConfig } from '../../types/theme'; +import { DependencyChecker } from '../../services/dependency-checker'; +import { PerformanceMonitor } from '../../services/performance-monitor'; +import { CacheManager } from '../../services/cache-manager'; + +/** + * 主题加载Hook + */ +export function useThemeLoader(themeName: string) { + const [theme, setTheme] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const loadTheme = async () => { + const monitor = PerformanceMonitor.startMonitoring(`theme:${themeName}`); + + try { + // 1. 检查缓存 + const cached = CacheManager.get(`theme:${themeName}`); + if (cached) { + setTheme(cached); + setLoading(false); + return; + } + + // 2. 获取主题配置 + const response = await fetch(`/api/themes/${themeName}`); + const themeConfig: ThemeConfig = await response.json(); + + // 3. 检查依赖 + if (themeConfig.dependencies) { + const dependenciesOk = await DependencyChecker.checkDependencies( + themeConfig.dependencies + ); + if (!dependenciesOk) { + throw new Error('主题依赖检查失败'); + } + } + + // 4. 加载主题样式 + if (themeConfig.globalStyles) { + const styleElement = document.createElement('style'); + styleElement.innerHTML = themeConfig.globalStyles; + document.head.appendChild(styleElement); + } + + // 5. 缓存主题配置 + CacheManager.set(`theme:${themeName}`, themeConfig, 3600000); // 1小时缓存 + + setTheme(themeConfig); + } catch (err) { + setError(err instanceof Error ? err.message : '加载主题失败'); + } finally { + setLoading(false); + monitor.end(); + } + }; + + loadTheme(); + }, [themeName]); + + return { theme, loading, error }; +} \ No newline at end of file diff --git a/frontend/services/cache-manager.ts b/frontend/services/cache-manager.ts new file mode 100644 index 0000000..a796c19 --- /dev/null +++ b/frontend/services/cache-manager.ts @@ -0,0 +1,41 @@ +// services/cache-manager.ts +/** + * 缓存管理服务 + */ +export class CacheManager { + private static cache = new Map(); + private static ttl = new Map(); + + /** + * 设置缓存 + * @param key 缓存键 + * @param value 缓存值 + * @param expiresIn 过期时间(毫秒) + */ + static set(key: string, value: any, expiresIn: number = 3600000) { + this.cache.set(key, value); + this.ttl.set(key, Date.now() + expiresIn); + } + + /** + * 获取缓存 + * @param key 缓存键 + * @returns 缓存值或null(如果已过期或不存在) + */ + static get(key: string): any { + if (this.ttl.has(key) && Date.now() > (this.ttl.get(key) || 0)) { + this.cache.delete(key); + this.ttl.delete(key); + return null; + } + return this.cache.get(key); + } + + /** + * 清除所有缓存 + */ + static clear() { + this.cache.clear(); + this.ttl.clear(); + } + } \ No newline at end of file diff --git a/frontend/services/dependency-checker.ts b/frontend/services/dependency-checker.ts new file mode 100644 index 0000000..cb8758e --- /dev/null +++ b/frontend/services/dependency-checker.ts @@ -0,0 +1,29 @@ +// services/dependency-checker.ts + +import { Dependency } from "../types/common"; + +/** + * 依赖检查器服务 + */ +export class DependencyChecker { + /** + * 检查依赖项是否满足要求 + * @param dependencies 需要检查的依赖项列表 + * @returns 是否所有依赖都满足要求 + */ + static async checkDependencies(dependencies: Dependency[]): Promise { + for (const dep of dependencies) { + const response = await fetch(`/api/dependencies/check`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(dep) + }); + + if (!response.ok) { + console.error(`依赖检查失败: ${dep.id}`); + return false; + } + } + return true; + } + } \ No newline at end of file diff --git a/frontend/services/performance-monitor.ts b/frontend/services/performance-monitor.ts new file mode 100644 index 0000000..e832439 --- /dev/null +++ b/frontend/services/performance-monitor.ts @@ -0,0 +1,54 @@ +// services/performance-monitor.ts +/** + * 性能指标接口 + */ +interface PerformanceMetrics { + loadTime: number; // 加载时间(毫秒) + memoryUsage: number; // 内存使用量(bytes) + errors: string[]; // 错误信息列表 + } + + /** + * 性能监控服务 + */ + export class PerformanceMonitor { + private static metrics: Map = new Map(); + + /** + * 开始监控性能 + * @param id 监控对象的唯一标识符 + */ + static startMonitoring(id: string) { + const startTime = performance.now(); + const startMemory = (performance as any).memory?.usedJSHeapSize || 0; + + return { + // 结束监控并记录指标 + end: () => { + const loadTime = performance.now() - startTime; + const memoryUsage = ((performance as any).memory?.usedJSHeapSize || 0) - startMemory; + + this.metrics.set(id, { + loadTime, + memoryUsage, + errors: [] + }); + }, + + // 记录错误信息 + error: (err: string) => { + const metrics = this.metrics.get(id) || { loadTime: 0, memoryUsage: 0, errors: [] }; + metrics.errors.push(err); + this.metrics.set(id, metrics); + } + }; + } + + /** + * 获取性能指标 + * @param id 监控对象的唯一标识符 + */ + static getMetrics(id: string): PerformanceMetrics | undefined { + return this.metrics.get(id); + } + } \ No newline at end of file diff --git a/frontend/services/plugin-communication.ts b/frontend/services/plugin-communication.ts new file mode 100644 index 0000000..a07e6de --- /dev/null +++ b/frontend/services/plugin-communication.ts @@ -0,0 +1,39 @@ +// services/plugin-communication.ts +/** + * 消息处理器类型定义 + */ +type MessageHandler = (data: any) => void; + +/** + * 插件通信服务 + */ +export class PluginMessenger { + // 存储所有消息处理器 + private static handlers: Map> = new Map(); + + /** + * 订阅消息通道 + * @param channel 通道名称 + * @param handler 消息处理函数 + * @returns 取消订阅函数 + */ + static subscribe(channel: string, handler: MessageHandler) { + if (!this.handlers.has(channel)) { + this.handlers.set(channel, new Set()); + } + this.handlers.get(channel)?.add(handler); + + return () => { + this.handlers.get(channel)?.delete(handler); + }; + } + + /** + * 发布消息到指定通道 + * @param channel 通道名称 + * @param data 消息数据 + */ + static publish(channel: string, data: any) { + this.handlers.get(channel)?.forEach(handler => handler(data)); + } +} diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index c831684..6a26a99 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -1,3 +1,4 @@ +//main.tsx import * as React from "react"; import "./main.css" import DynamicPage from "./page/page.tsx" @@ -7,7 +8,7 @@ import {createContext} from "react"; export const serverAddressContext=createContext("localhost:8080") // 动态路由 const RouterListener: React.FC = () => { - let pathname = location.pathname.split("/"); + const pathname = location.pathname.split("/"); console.log(pathname) return ( @@ -17,7 +18,7 @@ const RouterListener: React.FC = () => { } -ReactDOM.createRoot(document.getElementById("root")).render( +ReactDOM.createRoot(document.getElementById("root")!).render( diff --git a/frontend/src/page/page.tsx b/frontend/src/page/page.tsx index 5f0d35d..51852de 100644 --- a/frontend/src/page/page.tsx +++ b/frontend/src/page/page.tsx @@ -1,3 +1,4 @@ +// page/page.tsx import React from "react"; const THEMEPATH= "../../themes" import {serverAddressContext} from "../main.tsx"; diff --git a/frontend/types/common.ts b/frontend/types/common.ts new file mode 100644 index 0000000..dcc412d --- /dev/null +++ b/frontend/types/common.ts @@ -0,0 +1,18 @@ +// types/common.ts +/** + * 版本信息接口 + */ +export interface VersionInfo { + major: number; // 主版本号 - 不兼容的API修改 + minor: number; // 次版本号 - 向下兼容的功能性新增 + patch: number; // 修订号 - 向下兼容的问题修正 +} + +/** + * 依赖项配置接口 + */ +export interface Dependency { + id: string; // 依赖项的唯一标识符 + version: string; // 依赖项的版本要求 + type: 'plugin' | 'theme'; // 依赖项类型:插件或主题 +} \ No newline at end of file diff --git a/frontend/types/plugin.ts b/frontend/types/plugin.ts new file mode 100644 index 0000000..82889f8 --- /dev/null +++ b/frontend/types/plugin.ts @@ -0,0 +1,23 @@ +// types/plugin.ts +import {Dependency} from "./common"; + +/** + * 插件配置接口 + */ +export interface PluginConfig { + id: string; // 插件唯一标识符 + name: string; // 插件名称 + version: string; // 插件版本 + displayName: string; // 插件显示名称 + description?: string; // 插件描述 + author?: string; // 插件作者 + enabled: boolean; // 插件是否启用 + icon?: string; // 插件图标URL + adminPath?: string; // 插件管理页面路径 + entry: string; // 插件入口组件路径 + dependencies?: Dependency[]; // 插件依赖项 + performance?: { + maxLoadTime?: number; // 最大加载时间(毫秒) + maxMemoryUsage?: number; // 最大内存使用量(bytes) + }; +} \ No newline at end of file diff --git a/frontend/types/theme.ts b/frontend/types/theme.ts new file mode 100644 index 0000000..4904541 --- /dev/null +++ b/frontend/types/theme.ts @@ -0,0 +1,20 @@ +// types/theme.ts +import {Dependency} from "./common.ts"; + +/** + * 主题配置接口 + */ +export interface ThemeConfig { + name: string; // 主题的唯一名称标识符 + version: string; // 主题版本 + displayName: string; // 主题显示名称 + description?: string; // 主题描述 + author?: string; // 主题作者 + preview?: string; // 主题预览图URL + globalStyles?: string; // 主题全局样式 + dependencies?: Dependency[]; // 主题依赖项 + performance?: { + maxLoadTime?: number; // 最大加载时间(毫秒) + maxMemoryUsage?: number; // 最大内存使用量(bytes) + }; +} \ No newline at end of file