Skip to content

创建第一个插件

本指南将带你创建第一个 Fastdotnet 插件,了解完整的插件开发流程。

⚠️ 重要提示:Fastdotnet 采用插件化架构,所有功能都应该以插件形式开发,非特殊情况不修改框架底座


📋 学习目标

完成本教程后,你将学会:

  • ✅ 使用 CLI 工具创建插件项目
  • ✅ 理解插件项目结构
  • ✅ 开发后端 API
  • ✅ 开发前端页面
  • ✅ 调试和测试插件

🎯 项目场景

我们将创建一个简单的任务管理插件

  • 创建任务
  • 查看任务列表
  • 更新任务状态
  • 删除任务

🔧 第一步:安装 CLI 工具

1. 安装 Fastdotnet.Plugin.CLI

bash
dotnet tool install -g Fastdotnet.Plugin.CLI

2. 验证安装

bash
fd-plugin --version

应该输出版本号,例如:1.0.0

3. 更新到最新版本(推荐)

bash
dotnet tool update -g Fastdotnet.Plugin.CLI

💡 提示:确保使用最新版本的 CLI 工具,以保证生成的插件与当前框架兼容。


🚀 第二步:创建插件项目

方式一:交互式模式(推荐新手)

bash
fd-plugin

按照提示输入:

插件名称(英文,用于命名空间,例如:MyPlugin): TaskManager
插件显示名称(中文,例如:我的插件): 任务管理
官网申请的 PluginId: 你的PluginId
插件描述: 一个简单的任务管理插件
输出目录: .
是否包含前端项目? Yes
是否生成 .sln 解决方案文件? No

方式二:命令行模式

bash
fd-plugin create \
  --name TaskManager \
  --plugin-id YOUR_PLUGIN_ID \
  --display-name "任务管理" \
  --description "一个简单的任务管理插件" \
  --output ./plugins \
  --include-frontend

⚠️ 注意:你需要从 Fastdotnet 官网 申请唯一的 PluginId。


📁 第三步:了解项目结构

生成的项目结构如下:

TaskManager/
├── Backend/                    # 后端项目 (.NET 10)
│   ├── TaskManager.csproj
│   ├── TaskManagerPlugin.cs   # 插件入口类
│   ├── plugin.json            # 插件元数据
│   ├── Controllers/           # API 控制器
│   ├── Services/              # 业务服务
│   ├── Dto/                   # 数据传输对象
│   ├── Entities/              # 数据实体
│   └── Initializers/          # 初始化器

└── Frontend/                   # 前端项目 (Vue 3)
    ├── TaskManager.Admin/     # 管理端
    │   ├── src/
    │   ├── vite.config.ts
    │   └── package.json

    └── TaskManager.App/       # 应用端
        ├── src/
        ├── vite.config.ts
        └── package.json

💻 第四步:开发后端 API

1. 打开后端项目

bash
cd TaskManager/Backend
code .

2. 创建任务实体

Entities/ 目录下创建 TaskItem.cs

csharp
using SqlSugar;

namespace TaskManager.Entities
{
    /// <summary>
    /// 任务实体
    /// </summary>
    [SugarTable("task_manager_tasks")]
    public class TaskItem : BaseEntity
    {
        /// <summary>
        /// 任务标题
        /// </summary>
        [SugarColumn(Length = 200, IsNullable = false)]
        public string Title { get; set; }

        /// <summary>
        /// 任务描述
        /// </summary>
        [SugarColumn(Length = 1000, IsNullable = true)]
        public string? Description { get; set; }

        /// <summary>
        /// 任务状态:0-待办,1-进行中,2-已完成
        /// </summary>
        public int Status { get; set; } = 0;

        /// <summary>
        /// 优先级:1-低,2-中,3-高
        /// </summary>
        public int Priority { get; set; } = 2;

        /// <summary>
        /// 截止日期
        /// </summary>
        public DateTime? DueDate { get; set; }
    }
}

3. 创建控制器

Controllers/ 目录下创建 TaskController.cs

csharp
using Microsoft.AspNetCore.Mvc;
using TaskManager.Entities;
using Fastdotnet.Core.Controllers;
using Fastdotnet.Core.IService;

namespace TaskManager.Controllers
{
    /// <summary>
    /// 任务管理控制器
    /// </summary>
    [Route("api/task-manager/[controller]")]
    public class TaskController : GenericControllerBase<TaskItem>
    {
        public TaskController(IRepository<TaskItem> repository) 
            : base(repository)
        {
        }

        // 自动继承标准 CRUD API:
        // GET    /api/task-manager/task              - 获取列表
        // GET    /api/task-manager/task/{id}         - 获取详情
        // POST   /api/task-manager/task              - 创建任务
        // PUT    /api/task-manager/task/{id}         - 更新任务
        // DELETE /api/task-manager/task/{id}         - 删除任务
    }
}

4. 配置菜单

Initializers/ 目录下创建 TaskMenuInitializer.cs

csharp
using Fastdotnet.Core.Initializers;
using Fastdotnet.Core.Entities;

namespace TaskManager.Initializers
{
    public class TaskMenuInitializer : IApplicationInitializer
    {
        public async Task InitializeAsync()
        {
            var menus = new List<FdMenu>
            {
                new FdMenu 
                { 
                    Title = "任务管理",
                    Code = "MENU_CODE_TASK_MANAGER",
                    Path = "/micro/{PluginId}/admin/tasks",
                    Icon = "ele-List",
                    Type = MenuType.Menu,
                    Belong = SystemCategory.Admin,
                    IsFdMicroApp = true,
                    Sort = 100
                },
            };
            
            // TODO: 添加菜单插入逻辑
        }
    }
}

🎨 第五步:开发前端页面

1. 安装依赖

bash
cd ../Frontend/TaskManager.Admin
pnpm install

2. 启动开发服务器

bash
pnpm dev

访问 http://localhost:8099 预览。

3. 创建任务列表页面

src/views/ 目录下创建 Tasks.vue

vue
<template>
  <div class="tasks-page">
    <el-card>
      <template #header>
        <div class="card-header">
          <span>任务列表</span>
          <el-button type="primary" @click="handleCreate">
            新建任务
          </el-button>
        </div>
      </template>

      <el-table :data="tasks" style="width: 100%">
        <el-table-column prop="title" label="标题" />
        <el-table-column prop="status" label="状态">
          <template #default="{ row }">
            <el-tag :type="getStatusType(row.status)">
              {{ getStatusText(row.status) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="priority" label="优先级" />
        <el-table-column label="操作">
          <template #default="{ row }">
            <el-button size="small" @click="handleEdit(row)">
              编辑
            </el-button>
            <el-button size="small" type="danger" @click="handleDelete(row)">
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-card>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import axios from 'axios'

const tasks = ref([])

// 获取任务列表
const fetchTasks = async () => {
  try {
    const response = await axios.get('/api/task-manager/task')
    tasks.value = response.data.data
  } catch (error) {
    ElMessage.error('获取任务列表失败')
  }
}

// 状态映射
const getStatusType = (status: number) => {
  const types = ['info', 'warning', 'success']
  return types[status] || 'info'
}

const getStatusText = (status: number) => {
  const texts = ['待办', '进行中', '已完成']
  return texts[status] || '未知'
}

// 操作方法
const handleCreate = () => {
  ElMessage.info('新建任务功能待实现')
}

const handleEdit = (row: any) => {
  ElMessage.info('编辑任务功能待实现')
}

const handleDelete = async (row: any) => {
  try {
    await axios.delete(`/api/task-manager/task/${row.id}`)
    ElMessage.success('删除成功')
    fetchTasks()
  } catch (error) {
    ElMessage.error('删除失败')
  }
}

onMounted(() => {
  fetchTasks()
})
</script>

<style scoped>
.tasks-page {
  padding: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
</style>

4. 配置路由

编辑 src/router/index.ts

typescript
import { createRouter, createWebHistory } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'

const routes: RouteRecordRaw[] = [
  {
    path: '/tasks',
    name: 'Tasks',
    component: () => import('../views/Tasks.vue')
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

🧪 第六步:调试和测试

1. 构建后端

bash
cd ../../Backend
dotnet build -c Debug

2. 复制到宿主应用

bash
# Windows PowerShell
copy bin\Debug\net10.0\*.dll D:\Fastdotnet\Backend\Fastdotnet.WebApi\bin\Debug\net10.0\Plugins\YOUR_PLUGIN_ID\dependencies\

# Linux/Mac
cp bin/Debug/net10.0/*.dll /path/to/Fastdotnet/WebApi/bin/Debug/net10.0/Plugins/YOUR_PLUGIN_ID/dependencies/

3. 启动宿主应用

bash
cd D:\Fastdotnet\Backend\Fastdotnet.WebApi
dotnet run

4. 测试 API

访问 http://localhost:18889/swagger,查找 TaskManager 相关的接口进行测试。

5. 测试前端

确保主应用已启动并配置了 qiankun 微前端容器,然后访问对应的路由查看页面。


📦 第七步:打包发布

1. 构建后端

bash
cd Backend
dotnet publish -c Release -o ../publish/{PluginId}/dependencies

2. 构建前端

bash
cd ../Frontend/TaskManager.Admin
pnpm build

cd ../TaskManager.App
pnpm build

3. 打包插件

bash
cd ../publish/{PluginId}
zip -r ../../TaskManager.zip .

4. 上传到插件市场

登录 Fastdotnet 插件市场,上传 ZIP 文件。


📚 学习资源


💡 常见问题

Q: 为什么不能直接修改框架底座?

A: Fastdotnet 采用插件化架构的优势:

  • ✅ 框架稳定性 - 底座不改动,保证系统稳定
  • ✅ 功能隔离 - 插件独立,互不影响
  • ✅ 热插拔 - 可以动态加载和卸载
  • ✅ 易于维护 - 每个插件独立开发和测试
  • ✅ 团队协作 - 不同团队可以并行开发不同插件

Q: 如何获取 PluginId?

A: 访问 Fastdotnet 官网,在开发者中心申请唯一的 PluginId。

Q: 插件开发有什么最佳实践?

A:

  1. 参考 PluginA 演示插件的代码结构
  2. 遵循命名规范
  3. 编写清晰的注释
  4. 做好错误处理
  5. 及时更新文档

Q: 如何调试插件?

A:

  1. 将编译后的 DLL 复制到宿主应用的 Plugins 目录
  2. 启动宿主应用
  3. 使用 Visual Studio 附加到进程调试
  4. 查看日志文件排查问题

🎉 恭喜!

你已经完成了第一个 Fastdotnet 插件的开发!

下一步:

  • 📖 深入学习 PluginA 演示插件
  • 🔧 完善你的插件功能
  • 📦 发布到插件市场
  • 🤝 与其他开发者分享经验

祝你开发愉快!🚀

Released under the MIT License.