前端:实现extension接口,后端:修复数据库字段错误
This commit is contained in:
parent
86ad0fdb29
commit
2b44435c2a
@ -7,11 +7,11 @@ CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|||||||
--- 用户权限枚举
|
--- 用户权限枚举
|
||||||
CREATE TYPE privilege_level AS ENUM ('visitor', 'contributor', 'administrators');
|
CREATE TYPE privilege_level AS ENUM ('visitor', 'contributor', 'administrators');
|
||||||
--- 用户信息表
|
--- 用户信息表
|
||||||
CREATE TABLE person
|
CREATE TABLE persons
|
||||||
(
|
(
|
||||||
person_name VARCHAR(100) PRIMARY KEY, --- 用户名
|
person_name VARCHAR(100) PRIMARY KEY, --- 用户名
|
||||||
person_email VARCHAR(255) UNIQUE NOT NULL, --- 用户邮箱
|
person_email VARCHAR(255) UNIQUE NOT NULL, --- 用户邮箱
|
||||||
person_picture VARCHAR(255), --- 用户头像
|
person_icon VARCHAR(255), --- 用户头像
|
||||||
person_password VARCHAR(255) NOT NULL, --- 用户密码
|
person_password VARCHAR(255) NOT NULL, --- 用户密码
|
||||||
person_created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, --- 用户创建时间
|
person_created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, --- 用户创建时间
|
||||||
person_updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, --- 用户更新时间
|
person_updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, --- 用户更新时间
|
||||||
@ -28,7 +28,7 @@ CREATE TABLE pages
|
|||||||
page_id SERIAL PRIMARY KEY, --- 独立页面唯一id主键
|
page_id SERIAL PRIMARY KEY, --- 独立页面唯一id主键
|
||||||
page_meta_keywords VARCHAR(255) NOT NULL, ---页面mata关键字
|
page_meta_keywords VARCHAR(255) NOT NULL, ---页面mata关键字
|
||||||
page_meta_description VARCHAR(255) NOT NULL, ---页面mata描述
|
page_meta_description VARCHAR(255) NOT NULL, ---页面mata描述
|
||||||
post_title VARCHAR(255) NOT NULL, --- 文章标题
|
page_title VARCHAR(255) NOT NULL, --- 文章标题
|
||||||
page_content TEXT NOT NULL, --- 独立页面内容
|
page_content TEXT NOT NULL, --- 独立页面内容
|
||||||
page_mould VARCHAR(50), --- 独立页面模板名称
|
page_mould VARCHAR(50), --- 独立页面模板名称
|
||||||
page_fields JSON, --- 自定义字段
|
page_fields JSON, --- 自定义字段
|
||||||
@ -47,8 +47,8 @@ CREATE TABLE posts
|
|||||||
post_content TEXT NOT NULL, --- 文章内容
|
post_content TEXT NOT NULL, --- 文章内容
|
||||||
post_status publication_status DEFAULT 'draft', --- 文章状态
|
post_status publication_status DEFAULT 'draft', --- 文章状态
|
||||||
post_editor BOOLEAN DEFAULT FALSE, --- 文章是否编辑未保存
|
post_editor BOOLEAN DEFAULT FALSE, --- 文章是否编辑未保存
|
||||||
posts_unsaved_content TEXT, --- 未保存的文章
|
post_unsaved_content TEXT, --- 未保存的文章
|
||||||
posts_path VARCHAR(255), --- 文章路径
|
post_path VARCHAR(255), --- 文章路径
|
||||||
post_created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, --- 文章创建时间
|
post_created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, --- 文章创建时间
|
||||||
post_updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, --- 文章更新时间
|
post_updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, --- 文章更新时间
|
||||||
post_published_at TIMESTAMP, --- 文章发布时间
|
post_published_at TIMESTAMP, --- 文章发布时间
|
||||||
@ -58,7 +58,7 @@ CREATE TABLE posts
|
|||||||
CREATE TABLE tags
|
CREATE TABLE tags
|
||||||
(
|
(
|
||||||
tag_name VARCHAR(50) PRIMARY KEY CHECK (LOWER(tag_name) = tag_name), --- 标签名称主键
|
tag_name VARCHAR(50) PRIMARY KEY CHECK (LOWER(tag_name) = tag_name), --- 标签名称主键
|
||||||
tag_picture VARCHAR(255) --- 标签图标
|
tag_icon VARCHAR(255) --- 标签图标
|
||||||
);
|
);
|
||||||
--- 文章与标签的关系表
|
--- 文章与标签的关系表
|
||||||
CREATE TABLE post_tags
|
CREATE TABLE post_tags
|
||||||
|
2
frontend/app/env.d.ts
vendored
2
frontend/app/env.d.ts
vendored
@ -7,10 +7,10 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
interface ImportMetaEnv {
|
interface ImportMetaEnv {
|
||||||
readonly VITE_APP_TYPE: boolean; //用于判断是动态博客还是静态博客
|
|
||||||
readonly VITE_APP_API: string; // 用于访问API的基础URL
|
readonly VITE_APP_API: string; // 用于访问API的基础URL
|
||||||
readonly VITE_THEME_PATH: string; // 存储主题文件的目录路径
|
readonly VITE_THEME_PATH: string; // 存储主题文件的目录路径
|
||||||
readonly VITE_CONTENT_PATH: string; //mark文章存储的位置
|
readonly VITE_CONTENT_PATH: string; //mark文章存储的位置
|
||||||
|
readonly VITE_CONTENT_STATIC_PATH: string; //导出文章静态存储的位置
|
||||||
readonly VITE_PLUGINS_PATH: string; // 存储插件文件的目录路径
|
readonly VITE_PLUGINS_PATH: string; // 存储插件文件的目录路径
|
||||||
readonly VITE_ASSETS_PATH: string; // 存储静态资源的目录路径
|
readonly VITE_ASSETS_PATH: string; // 存储静态资源的目录路径
|
||||||
}
|
}
|
||||||
|
@ -1,40 +1,25 @@
|
|||||||
import {
|
import { Meta, Outlet, Scripts, ScrollRestoration } from "@remix-run/react";
|
||||||
Links,
|
import type { LoaderFunction } from "@remix-run/node";
|
||||||
Meta,
|
import { useLoaderData } from "@remix-run/react";
|
||||||
Outlet,
|
import { ThemeProvider } from "hooks/themeContext";
|
||||||
Scripts,
|
import { createContext, useContext, ReactNode } from 'react';
|
||||||
ScrollRestoration,
|
|
||||||
} from "@remix-run/react";
|
|
||||||
import type { LinksFunction } from "@remix-run/node";
|
|
||||||
|
|
||||||
import "./tailwind.css";
|
import "./tailwind.css";
|
||||||
|
|
||||||
export const links: LinksFunction = () => [
|
|
||||||
{ rel: "preconnect", href: "https://fonts.googleapis.com" },
|
|
||||||
{
|
|
||||||
rel: "preconnect",
|
|
||||||
href: "https://fonts.gstatic.com",
|
|
||||||
crossOrigin: "anonymous",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
rel: "stylesheet",
|
|
||||||
href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export function Layout({ children }: { children: React.ReactNode }) {
|
export function Layout({ children }: { children: React.ReactNode }) {
|
||||||
console.log(import.meta.env.VITE_THEME_NAME);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charSet="utf-8" />
|
<meta charSet="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1"
|
||||||
|
/>
|
||||||
<Meta />
|
<Meta />
|
||||||
<Links />
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<ThemeProvider>
|
||||||
{children}
|
{children}
|
||||||
|
</ThemeProvider>
|
||||||
<ScrollRestoration />
|
<ScrollRestoration />
|
||||||
<Scripts />
|
<Scripts />
|
||||||
</body>
|
</body>
|
||||||
@ -43,5 +28,9 @@ export function Layout({ children }: { children: React.ReactNode }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return <Outlet />;
|
return (
|
||||||
|
<Layout>
|
||||||
|
<Outlet />
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
}
|
}
|
23
frontend/hooks/themeContext.tsx
Normal file
23
frontend/hooks/themeContext.tsx
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// service/theme/themeContext.tsx
|
||||||
|
import { createContext, useContext, ReactNode } from 'react';
|
||||||
|
import { ThemeService } from 'service/themeService';
|
||||||
|
|
||||||
|
const ThemeContext = createContext<ThemeService | undefined>(undefined);
|
||||||
|
|
||||||
|
export function ThemeProvider({ children }: { children: ReactNode }) {
|
||||||
|
const themeService = ThemeService.getInstance();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeContext.Provider value={themeService}>
|
||||||
|
{children}
|
||||||
|
</ThemeContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useTheme(): ThemeService {
|
||||||
|
const context = useContext(ThemeContext);
|
||||||
|
if (context === undefined) {
|
||||||
|
throw new Error('useTheme must be used within a ThemeProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
84
frontend/service/extensionService.ts
Normal file
84
frontend/service/extensionService.ts
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// File path: service/extensionService.ts
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ExtensionManage 是一个单例类,用于管理扩展的实例。
|
||||||
|
* 提供注册、触发和移除插件扩展的功能。
|
||||||
|
*/
|
||||||
|
import { ExtensionType } from "types/extensionType";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
class ExtensionManage {
|
||||||
|
/** 存储扩展的映射,键为扩展名称,值为插件名称和扩展的集合 */
|
||||||
|
private extensions: Map<string, Set<{ pluginName: string; extension: ExtensionType }>> = new Map();
|
||||||
|
/** ExtensionManage 的唯一实例 */
|
||||||
|
private static instance: ExtensionManage;
|
||||||
|
|
||||||
|
/** 私有构造函数,防止外部实例化 */
|
||||||
|
private constructor() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 ExtensionManage 的唯一实例。
|
||||||
|
* @returns {ExtensionManage} 返回 ExtensionManage 的唯一实例。
|
||||||
|
*/
|
||||||
|
public static getInstance(): ExtensionManage {
|
||||||
|
if (!this.instance) {
|
||||||
|
this.instance = new ExtensionManage();
|
||||||
|
}
|
||||||
|
return this.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 注册扩展 */
|
||||||
|
private register(extensionName: string, pluginName: string, extension: ExtensionType) {
|
||||||
|
const handlers = this.extensions.get(extensionName) || new Set();
|
||||||
|
handlers.add({ pluginName, extension });
|
||||||
|
this.extensions.set(extensionName, handlers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 执行扩展方法 */
|
||||||
|
private executeExtensionMethod<T>(extensionName: string, method: keyof ExtensionType, ...args: any[]): Set<T> {
|
||||||
|
const result = new Set<T>();
|
||||||
|
const handlers = this.extensions.get(extensionName);
|
||||||
|
|
||||||
|
if (handlers) {
|
||||||
|
handlers.forEach(({ extension }) => {
|
||||||
|
const methodFunction = extension[method];
|
||||||
|
if (methodFunction) {
|
||||||
|
try {
|
||||||
|
const value = methodFunction(...args);
|
||||||
|
if (value && (typeof value === 'string' || React.isValidElement(value))) {
|
||||||
|
result.add(value as T);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error executing hook ${extensionName}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 触发扩展的动作 */
|
||||||
|
private triggerAction(extensionName: string, ...args: any[]): void {
|
||||||
|
this.executeExtensionMethod<void>(extensionName, 'action', ...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 触发扩展的组件 */
|
||||||
|
private triggerComponent(extensionName: string, ...args: any[]): Set<React.FC> {
|
||||||
|
return this.executeExtensionMethod<React.FC>(extensionName, 'component', ...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 触发扩展的文本 */
|
||||||
|
private triggerText(extensionName: string, ...args: any[]): Set<string> {
|
||||||
|
return this.executeExtensionMethod<string>(extensionName, 'text', ...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 移除指定插件的扩展 */
|
||||||
|
private removePluginExtensions(pluginName: string) {
|
||||||
|
this.extensions.forEach((handlers, extensionName) => {
|
||||||
|
const newHandlers = new Set(
|
||||||
|
Array.from(handlers).filter(handler => handler.pluginName !== pluginName)
|
||||||
|
);
|
||||||
|
this.extensions.set(extensionName, newHandlers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
24
frontend/service/pluginService.ts
Normal file
24
frontend/service/pluginService.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { PluginConfig ,PluginType ,PluginConfiguration} from "types/pluginType";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export class PluginService {
|
||||||
|
private static pluginInstance: PluginService | null = null; // 单例实例
|
||||||
|
private pluginComponents: Map<PluginType, Set<{
|
||||||
|
name:string,
|
||||||
|
configuration?:PluginConfiguration,
|
||||||
|
managePath?: string,
|
||||||
|
|
||||||
|
|
||||||
|
}>> = new Map(); // 插件组件缓存
|
||||||
|
private constructor (){};
|
||||||
|
|
||||||
|
public static getInstance(): PluginService {
|
||||||
|
if (!this.pluginInstance) {
|
||||||
|
this.pluginInstance = new PluginService();
|
||||||
|
}
|
||||||
|
return this.pluginInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
52
frontend/service/themeService.ts
Normal file
52
frontend/service/themeService.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// service/theme/themeService.ts
|
||||||
|
import type { ThemeConfig } from 'types/themeType';
|
||||||
|
|
||||||
|
export class ThemeService {
|
||||||
|
private static themeInstance: ThemeService; // 单例实例
|
||||||
|
private themeConfig: ThemeConfig | null = null; // 当前主题配置
|
||||||
|
private themeComponents: Map<string, React.ComponentType> = new Map(); // 主题组件缓存
|
||||||
|
|
||||||
|
private constructor() { } // 私有构造函数,防止外部实例化
|
||||||
|
|
||||||
|
// 获取单例实例
|
||||||
|
public static getInstance(): ThemeService {
|
||||||
|
if (!ThemeService.themeInstance) {
|
||||||
|
ThemeService.themeInstance = new ThemeService();
|
||||||
|
}
|
||||||
|
return ThemeService.themeInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载主题
|
||||||
|
async loadTheme(themeConfig: ThemeConfig): Promise<void> {
|
||||||
|
this.themeConfig = themeConfig; // 设置当前主题
|
||||||
|
await this.loadThemeComponents(themeConfig); // 加载主题组件
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载主题组件
|
||||||
|
private async loadThemeComponents(config:ThemeConfig): Promise<void> {
|
||||||
|
// 清除现有组件缓存
|
||||||
|
this.themeComponents.clear();
|
||||||
|
|
||||||
|
// 动态导入主题入口组件
|
||||||
|
const entryComponent = await import(config.entry);
|
||||||
|
this.themeComponents.set('entry', entryComponent.default); // 缓存入口路径
|
||||||
|
|
||||||
|
// 加载所有模板组件
|
||||||
|
for (const [key, template] of config.templates.entries()) {
|
||||||
|
const component = await import(template.path);
|
||||||
|
this.themeComponents.set(key, component.default); // 缓存模板组件
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取指定模板名称的组件
|
||||||
|
getComponent(templateName: string): React.ComponentType | null {
|
||||||
|
return this.themeComponents.get(templateName) || null; // 返回组件或null
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前主题配置
|
||||||
|
getCurrentTheme(): ThemeConfig | null {
|
||||||
|
return this.currentTheme; // 返回当前主题配置
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
25
frontend/theme/default/theme.config.ts
Normal file
25
frontend/theme/default/theme.config.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { ThemeConfig } from "types/themeType";
|
||||||
|
|
||||||
|
export const themeConfig: ThemeConfig = {
|
||||||
|
name: 'default',
|
||||||
|
displayName: '默认主题',
|
||||||
|
version: '1.0.0',
|
||||||
|
description: '一个简约风格的博客主题',
|
||||||
|
author: 'lsy',
|
||||||
|
entry: './index.tsx',
|
||||||
|
templates: new Map([
|
||||||
|
['page', {
|
||||||
|
path: './templates/page',
|
||||||
|
name: '文章列表模板',
|
||||||
|
description: '博客首页展示模板'
|
||||||
|
}],
|
||||||
|
]),
|
||||||
|
|
||||||
|
settingsSchema: undefined,
|
||||||
|
routes: {
|
||||||
|
post: "",
|
||||||
|
tag: "",
|
||||||
|
category: "",
|
||||||
|
page: ""
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,8 @@
|
|||||||
"paths": {
|
"paths": {
|
||||||
"theme/*":["./theme/*"],
|
"theme/*":["./theme/*"],
|
||||||
"types/*":["./types/*"],
|
"types/*":["./types/*"],
|
||||||
|
"service/*":["./service/*"],
|
||||||
|
"hooks/*":["./hooks/*"],
|
||||||
},
|
},
|
||||||
|
|
||||||
// Vite takes care of building everything, not tsc.
|
// Vite takes care of building everything, not tsc.
|
||||||
|
20
frontend/types/extensionType.ts
Normal file
20
frontend/types/extensionType.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* File path: types/extensionType.ts
|
||||||
|
*
|
||||||
|
* 该文件定义了扩展类型接口 ExtensionType,包含可选的操作、组件和文本生成函数。
|
||||||
|
*
|
||||||
|
* 接口属性说明:
|
||||||
|
* - action: 可选的操作函数,接受任意参数并返回 void。
|
||||||
|
* - component: 可选的组件函数,接受任意参数并返回一个 React 组件。
|
||||||
|
* - text: 可选的文本生成函数,接受任意参数并返回一个字符串。
|
||||||
|
*/
|
||||||
|
export interface ExtensionType {
|
||||||
|
/** 可选的操作函数,接受任意参数并返回 void */
|
||||||
|
action?: (...args: any[]) => void;
|
||||||
|
|
||||||
|
/** 可选的组件函数,接受任意参数并返回一个 React 组件 */
|
||||||
|
component?: (...args: any[]) => React.FC;
|
||||||
|
|
||||||
|
/** 可选的文本生成函数,接受任意参数并返回一个字符串 */
|
||||||
|
text?: (...args: any[]) => string;
|
||||||
|
}
|
@ -1,41 +0,0 @@
|
|||||||
// File path: types/plugin.ts
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 插件配置接口
|
|
||||||
*
|
|
||||||
* 该接口定义了插件的基本配置,包括插件的名称、版本、描述、作者等信息。
|
|
||||||
* 还包括插件的生命周期钩子和依赖项的配置。
|
|
||||||
*/
|
|
||||||
export interface PluginConfig {
|
|
||||||
name: string; // 插件名称
|
|
||||||
version: string; // 插件版本
|
|
||||||
displayName: string; // 插件显示名称
|
|
||||||
description?: string; // 插件描述(可选)
|
|
||||||
author?: string; // 插件作者(可选)
|
|
||||||
enabled: boolean; // 插件是否启用
|
|
||||||
icon?: string; // 插件图标URL(可选)
|
|
||||||
managePath?: string; // 插件管理页面路径(可选)
|
|
||||||
entry: string; // 插件入口组件路径
|
|
||||||
// 主题配置
|
|
||||||
settingsSchema?: {
|
|
||||||
type: string; // 配置类型
|
|
||||||
properties: Record<string, {
|
|
||||||
type: string; // 属性类型
|
|
||||||
title: string; // 属性标题
|
|
||||||
description?: string; // 属性描述(可选)
|
|
||||||
data?: any; // 额外数据(可选)
|
|
||||||
}>;
|
|
||||||
};
|
|
||||||
// 依赖
|
|
||||||
dependencies?: {
|
|
||||||
plugins?: string[]; // 依赖的插件列表(可选)
|
|
||||||
themes?: string[]; // 依赖的主题列表(可选)
|
|
||||||
};
|
|
||||||
// 插件生命周期钩子
|
|
||||||
hooks?: {
|
|
||||||
onInstall?: string; // 安装时调用的钩子(可选)
|
|
||||||
onUninstall?: string; // 卸载时调用的钩子(可选)
|
|
||||||
onEnable?: string; // 启用时调用的钩子(可选)
|
|
||||||
onDisable?: string; // 禁用时调用的钩子(可选)
|
|
||||||
};
|
|
||||||
}
|
|
48
frontend/types/pluginType.ts
Normal file
48
frontend/types/pluginType.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// File path: types/pluginType.ts
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件配置接口
|
||||||
|
*
|
||||||
|
* 该接口定义了插件的基本配置,包括插件的名称、版本、描述、作者等信息。
|
||||||
|
* 还包括插件的生命周期钩子和依赖项的配置。
|
||||||
|
*/
|
||||||
|
export interface PluginConfig {
|
||||||
|
name: string; // 插件名称
|
||||||
|
version: string; // 插件版本
|
||||||
|
displayName: string; // 插件显示名称
|
||||||
|
description?: string; // 插件描述(可选)
|
||||||
|
author?: string; // 插件作者(可选)
|
||||||
|
enabled: boolean; // 插件是否启用
|
||||||
|
icon?: string; // 插件图标URL(可选)
|
||||||
|
managePath?: string; // 插件管理页面路径(可选)
|
||||||
|
configuration?: PluginConfiguration; // 插件配置
|
||||||
|
dependencies?: {
|
||||||
|
plugins?: string[]; // 依赖的插件列表(可选)
|
||||||
|
themes?: string[]; // 依赖的主题列表(可选)
|
||||||
|
};
|
||||||
|
hooks?: {
|
||||||
|
onInstall?: (context: any) => {}; // 安装时调用的钩子(可选)
|
||||||
|
onUninstall?: (context: any) => {}; // 卸载时调用的钩子(可选)
|
||||||
|
onEnable?: (context: any) => {}; // 启用时调用的钩子(可选)
|
||||||
|
onDisable?: (context: any) => {}; // 禁用时调用的钩子(可选)
|
||||||
|
};
|
||||||
|
routs: Set<{
|
||||||
|
description?: string; // 路由描述(可选)
|
||||||
|
path: string; // 路由路径
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件配置接口
|
||||||
|
*
|
||||||
|
* 该接口定义了插件的配置类型及其属性。
|
||||||
|
*/
|
||||||
|
export interface PluginConfiguration {
|
||||||
|
type: string; // 配置类型
|
||||||
|
properties: Record<string, {
|
||||||
|
type: string; // 属性类型
|
||||||
|
title: string; // 属性标题
|
||||||
|
description?: string; // 属性描述(可选)
|
||||||
|
data: any; // 额外数据(可选)
|
||||||
|
}>;
|
||||||
|
}
|
34
frontend/types/templateType.ts
Normal file
34
frontend/types/templateType.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// File path: types/templateType.ts
|
||||||
|
/**
|
||||||
|
* 插件配置接口
|
||||||
|
*
|
||||||
|
* 该接口定义了模板的基本配置,包括依赖项、钩子和页面渲染函数。
|
||||||
|
*/
|
||||||
|
import React from "react";
|
||||||
|
import { ExtensionType } from "types/extensionType";
|
||||||
|
|
||||||
|
export interface TemplateConfig {
|
||||||
|
/**
|
||||||
|
* 依赖项配置
|
||||||
|
*
|
||||||
|
* 记录每个依赖字段的名称、描述和是否必填。
|
||||||
|
*/
|
||||||
|
dependencies: Record<string, {
|
||||||
|
name: string; // 依赖字段的名称
|
||||||
|
description?: string; // 依赖字段的描述信息
|
||||||
|
required?: boolean; // 依赖字段是否必填
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
extensions?: Record<string, {
|
||||||
|
description?: string;
|
||||||
|
extension: ExtensionType;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面渲染函数
|
||||||
|
*
|
||||||
|
* 接受参数并返回一个 React 组件。
|
||||||
|
*/
|
||||||
|
page(params: Map<string, string>): React.FC;
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// types/theme.ts
|
// File path: types/themeType.ts
|
||||||
/**
|
/**
|
||||||
* 主题配置和模板接口定义文件
|
* 主题配置和模板接口定义文件
|
||||||
* 该文件包含主题配置接口和主题模板接口的定义,用于主题管理和渲染。
|
* 该文件包含主题配置接口和主题模板接口的定义,用于主题管理和渲染。
|
||||||
@ -6,17 +6,18 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 主题配置接口
|
* 主题配置接口
|
||||||
|
* 定义主题的基本信息、模板、全局配置、依赖、钩子和路由。
|
||||||
*/
|
*/
|
||||||
export interface ThemeConfig {
|
export interface ThemeConfig {
|
||||||
name: string; // 主题的唯一标识符
|
name: string; // 主题的名称
|
||||||
displayName: string; // 主题的显示名称
|
displayName: string; // 主题的显示名称
|
||||||
version: string; // 主题的版本号
|
version: string; // 主题的版本号
|
||||||
description?: string; // 主题的描述信息
|
description?: string; // 主题的描述信息
|
||||||
author?: string; // 主题的作者信息
|
author?: string; // 主题的作者信息
|
||||||
entry: string; // 主题的入口组件路径
|
entry?: string; // 主题的入口路径
|
||||||
templates: Map<string, ThemeTemplate>; // 主题模板的映射表
|
templates: Map<string, ThemeTemplate>; // 主题模板的映射表
|
||||||
/** 主题全局配置 */
|
/** 主题全局配置 */
|
||||||
globalSettings: {
|
globalSettings?: {
|
||||||
layout?: string; // 主题的布局配置
|
layout?: string; // 主题的布局配置
|
||||||
css?: string; // 主题的CSS配置
|
css?: string; // 主题的CSS配置
|
||||||
};
|
};
|
||||||
@ -34,22 +35,23 @@ export interface ThemeConfig {
|
|||||||
};
|
};
|
||||||
/** 钩子 */
|
/** 钩子 */
|
||||||
hooks?: {
|
hooks?: {
|
||||||
beforeRender?: string; // 渲染前执行的钩子
|
onActivate?: () => {}; // 主题激活时执行的钩子
|
||||||
afterRender?: string; // 渲染后执行的钩子
|
onDeactivate?: () => {}; // 主题停用时执行的钩子
|
||||||
onActivate?: string; // 主题激活时执行的钩子
|
|
||||||
onDeactivate?: string; // 主题停用时执行的钩子
|
|
||||||
};
|
};
|
||||||
/** 路由 */
|
/** 路由 */
|
||||||
routes:{
|
routes: {
|
||||||
post:string; // 文章使用的模板
|
index: string; // 首页使用的模板
|
||||||
tag:string; // 标签使用的模板
|
post: string; // 文章使用的模板
|
||||||
category:string; // 分类使用的模板
|
tag: string; // 标签使用的模板
|
||||||
page:string; // 独立页面模板路径
|
category: string; // 分类使用的模板
|
||||||
|
error: string; // 错误页面用的模板
|
||||||
|
page: Map<string, string>; // 独立页面模板
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主题模板接口
|
* 主题模板接口
|
||||||
|
* 定义主题模板的基本信息,包括路径、名称和描述。
|
||||||
*/
|
*/
|
||||||
export interface ThemeTemplate {
|
export interface ThemeTemplate {
|
||||||
path: string; // 模板文件的路径
|
path: string; // 模板文件的路径
|
Loading…
Reference in New Issue
Block a user