Files
Academic-Affairs-System/samples/Jiaowu.SamplePlugin/SamplePlugin.cs
T
biss 05683e502a 第二阶段已完成:统一插件平台已从“内置功能开关”扩展为可安装、签名校验、版本激活和回滚的插件系统。
主要成果:
- 新增独立插件 SDK:[PluginContracts.cs (line 11)](E:/jiaowu/src/Jiaowu.Plugin.Abstractions/PluginContracts.cs:11)
- 支持 RSA-PSS/SHA-256 签名插件包、Host API 兼容性和 ZIP 安全检查:[PluginPackageValidator.cs (line 14)](E:/jiaowu/src/Jiaowu.Api/Infrastructure/Plugins/PluginPackageValidator.cs:14)
- 支持暂存、待激活、重启装载、失败记录、版本回滚:[PluginPackageService.cs (line 32)](E:/jiaowu/src/Jiaowu.Api/Infrastructure/Plugins/PluginPackageService.cs:32)
- 插件可注册控制器、服务、数据库迁移、后台任务和事件处理器
- 外部插件 API 统一使用 /api/plugin-extensions/{pluginId},并受启用状态中间件控制
- 插件中心新增 ZIP/SIG 上传、状态展示、激活、回滚和删除功能:[PluginsView.vue (line 212)](E:/jiaowu/web/src/views/PluginsView.vue:212)
- 提供可运行示例插件:[SamplePlugin.cs (line 10)](E:/jiaowu/samples/Jiaowu.SamplePlugin/SamplePlugin.cs:10)
- 提供打包签名脚本:[package-plugin.ps1](E:/jiaowu/scripts/package-plugin.ps1)
- 完整开发文档:[plugin-sdk.md (line 1)](E:/jiaowu/docs/plugin-sdk.md:1)
- 系统版本已调整为 3.0.0-beta1
2026-10-01 10:22:46 +08:00

61 lines
2.0 KiB
C#

using Jiaowu.Plugin.Abstractions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Jiaowu.SamplePlugin;
public sealed class SamplePluginModule : IJiaowuPluginModule
{
public void ConfigureServices(
IServiceCollection services,
IConfiguration configuration)
{
services.AddSingleton<SampleGreetingService>();
}
}
public sealed class SampleGreetingService
{
public string BuildGreeting() => "签名示例插件已由宿主成功装载。";
}
[ApiController]
[Authorize(Roles = "SuperAdmin")]
[Route("api/plugin-extensions/sample.hello")]
public sealed class SamplePluginController(SampleGreetingService greetings)
: ControllerBase
{
[HttpGet("greeting")]
public IActionResult GetGreeting() => Ok(new { message = greetings.BuildGreeting() });
}
public sealed class SamplePluginMigration : IPluginDatabaseMigration
{
public string PluginId => "sample.hello";
public string MigrationId => "001_initial";
public IReadOnlyList<string> GetStatements(PluginDatabaseProvider provider) =>
provider == PluginDatabaseProvider.Sqlite
? ["CREATE TABLE IF NOT EXISTS SamplePluginNotes (Id TEXT NOT NULL PRIMARY KEY, Content TEXT NOT NULL);"]
: ["CREATE TABLE IF NOT EXISTS `SamplePluginNotes` (`Id` char(36) NOT NULL, `Content` varchar(500) NOT NULL, PRIMARY KEY (`Id`)) CHARACTER SET utf8mb4;"];
}
public sealed class SamplePluginBackgroundTask(
ILogger<SamplePluginBackgroundTask> logger) : IPluginBackgroundTask
{
public string PluginId => "sample.hello";
public string Name => "sample-heartbeat";
public TimeSpan Interval => TimeSpan.FromHours(1);
public Task ExecuteAsync(
IServiceProvider services,
CancellationToken cancellationToken)
{
logger.LogInformation("示例插件后台任务正常运行。");
return Task.CompletedTask;
}
}