.NET集成飞书API最佳实践:基于Mud.Feishu的飞书二次开发实践

飞书作为一款集成化的办公平台,为企业提供了强大的组织管理和协作能力。其中,组织管理是构建高效团队协作体系的基础环节。本文将深入解析如何在飞书平台上进行全面的组织管理,包括部门、用户、用户角色、职级、职位等核心要素,帮助开发者更好地理解和运用飞书API进行组织相关操作。

Mud.Feishu框架的介绍

Mud.Feishu是一个专为.NET开发者设计的飞书API集成组件库,它封装了飞书开放平台的各种API接口,提供了更加友好和易用的编程接口。该组件基于ASP.NET Core框架开发,充分利用了.NET生态系统的优势,为开发者提供了现代化的开发体验。

技术架构与支持框架

Mud.Feishu组件完全基于.NET框架构建,充分利用了其依赖注入、配置管理、日志记录等核心功能。组件设计遵循.NET生态系统最佳实践,能够无缝集成到ASP.NET Core应用程序中。

在服务注册方面,Mud.Feishu采用了标准的ASP.NET Core扩展模式,通过AddFeishuApiService("FeishuSettings")方法将飞书服务注册到服务容器中,其中"FeishuSettings"为appsettings.json配置文件中的配置节名称。这种设计方式使得组件配置更加清晰,避免了直接传递IConfiguration对象可能带来的配置混乱问题。

第三方库依赖情况

Mud.Feishu组件在设计时尽量减少了对第三方库的依赖,以降低项目的复杂性和潜在的版本冲突风险。主要依赖包括:

  1. System.Text.Json - 用于JSON序列化和反序列化,这是.NET Core内置的高性能JSON处理库
  2. Microsoft.Extensions.Http - 用于配置和管理HTTP客户端,提供连接池、生命周期管理等功能
  3. Microsoft.Extensions.Options - 用于强类型配置绑定和验证
  4. Microsoft.Extensions.Logging - 用于记录组件运行日志

这些依赖都是.NET生态系统中的标准组件,确保了组件的稳定性和兼容性。

核心特性

Mud.Feishu组件具有以下核心特性:

  1. 全面的API覆盖 - 支持飞书开放平台的绝大部分API,包括用户管理、部门管理、消息发送、日历管理等
  2. 强类型支持 - 所有API请求和响应都具有明确的类型定义,提供完整的IntelliSense支持
  3. 自动令牌管理 - 自动处理访问令牌的获取、刷新和缓存,开发者无需关心令牌细节
  4. 内置重试机制 - 对于网络抖动等临时性错误,组件内置了智能重试机制
  5. 完善的异常处理 - 提供了丰富的异常类型,便于开发者进行精确的错误处理
  6. 可扩展设计 - 采用接口抽象设计,支持自定义扩展和替换组件内部实现

与原生飞书SDK的对比分析

为了更清晰地展示Mud.Feishu组件相对于原生SDK的优势,下面通过表格形式进行详细对比:

对比维度 原生SDK调用 Mud.Feishu组件 优势说明
开发效率 需要手动构造HTTP请求、处理响应、解析JSON等大量样板代码 只需调用简洁的接口方法,一行代码完成操作 大幅减少代码量,提高开发效率
类型安全 手动处理JSON序列化/反序列化,容易出现类型转换错误 提供完整的强类型支持,编译时就能发现类型错误 提高代码健壮性,减少运行时错误
令牌管理 需要手动获取、刷新和管理访问令牌 自动处理令牌获取和刷新机制 减少开发者负担,避免令牌管理错误
异常处理 需要手动处理各种网络异常和业务异常 提供统一的异常处理机制和明确的异常类型 简化异常处理逻辑,提高代码可读性
重试机制 需要手动实现重试逻辑 内置智能重试机制,自动处理网络抖动等问题 提高系统稳定性
可测试性 直接调用HTTP接口,难以进行单元测试 基于接口设计,易于进行Mock测试 提高代码质量和可维护性
文档完善度 需要在飞书官方文档中查找各个接口的详细说明 提供完整的中文API文档和示例代码 降低学习成本,快速上手
依赖管理 需要自行引入和管理各种第三方库 统一管理所有依赖,避免版本冲突 简化项目依赖管理

通过以上对比,Mud.Feishu组件在各个方面都优于原生SDK调用方式,特别是在开发效率和代码质量方面有显著提升。

使用Mud.Feishu的简单示例:

csharp 复制代码
// 使用Mud.Feishu
var result = await _feishuUserApi.CreateUserAsync(token, userRequest);

// 原生方式需要大量样板代码
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://open.feishu.cn/open-apis/contact/v3/users");
request.Headers.Add("Authorization", $"Bearer {token}");
var json = JsonSerializer.Serialize(userRequest);
request.Content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
// ... 更多处理代码

Mud.Feishu 的架构设计

Mud.Feishu 采用现代化的分层架构设计,将复杂的 HTTP 通信细节封装为简单易用的 API 接口,架构层次图如下:

架构层次图

scss 复制代码
┌─────────────────────────────────────────────────────────────┐
│                    应用层 (Application Layer)                  │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐ │
│  │   Controller    │  │    Service      │  │   Repository    │ │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│                   API 抽象层 (API Abstraction)                │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐ │
│  │ IFeishuV3User   │  │ IFeishuV3Dept   │  │ IFeishuV3Role   │ │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│                  核心服务层 (Core Services)                  │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐ │
│  │ TokenManager    │  │ HttpClient      │  │ ErrorHandler    │ │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│                  基础设施层 (Infrastructure)                │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐ │
│  │   Caching       │  │   Logging       │  │ Configuration   │ │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘ │
└─────────────────────────────────────────────────────────────┘

快速入门

安装Mud.Feishu

首先,我们需要安装Mud.Feishu组件库。可以通过NuGet包管理器进行安装:

bash 复制代码
dotnet add package Mud.Feishu

配置飞书应用

在开始使用飞书API之前,您需要在飞书开放平台创建一个应用,并获取AppId和AppSecret。具体步骤如下:

  1. 登录飞书开放平台(飞书开放平台
  2. 创建企业自建应用
  3. 获取AppId和AppSecret
  4. 配置应用权限,确保开通了所需的API权限

配置服务注册

在ASP.NET Core应用程序中,我们需要在Program.cs中注册飞书服务:

csharp 复制代码
var builder = WebApplication.CreateBuilder(args);

// 添加飞书服务
builder.Services.AddFeishuApiService("Feishu")
                .AddLogging(option => option.AddConsole());

var app = builder.Build();

配置文件设置

在appsettings.json中添加飞书配置:

json 复制代码
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Feishu": {
    "AppId": "your_feishu_app_id",
    "AppSecret": "your_feishu_app_secret",
    "BaseUrl": "https://open.feishu.cn"
  }
}

如何与ASP.NET Core集成

Mud.Feishu组件设计时充分考虑了与ASP.NET Core的集成,通过依赖注入机制,我们可以轻松地在控制器中使用飞书API。

控制器注入示例

csharp 复制代码
using Microsoft.AspNetCore.Mvc;
using Mud.Feishu;

[ApiController]
[Route("api/[controller]")]
public class FeishuController : ControllerBase
{
    private readonly IFeishuV3AuthenticationApi _authApi;
    private readonly IFeishuV3UserApi _userApi;
    private readonly IFeishuV3DepartmentsApi _departmentsApi;
    private readonly IFeishuV3RoleApi _roleApi;
    private readonly IFeishuV3JobLevelApi _jobLevelApi;
    private readonly IFeishuV3JobTitleApi _jobTitleApi;

    public FeishuController(
        IFeishuV3AuthenticationApi authApi, 
        IFeishuV3UserApi userApi,
        IFeishuV3DepartmentsApi departmentsApi,
        IFeishuV3RoleApi roleApi,
        IFeishuV3JobLevelApi jobLevelApi,
        IFeishuV3JobTitleApi jobTitleApi)
    {
        _authApi = authApi;
        _userApi = userApi;
        _departmentsApi = departmentsApi;
        _roleApi = roleApi;
        _jobLevelApi = jobLevelApi;
        _jobTitleApi = jobTitleApi;
    }
}

服务层使用示例

除了在控制器中直接使用,我们也可以在服务层中使用飞书API:

csharp 复制代码
public class OrganizationService
{
    private readonly IFeishuV3DepartmentsApi _departmentsApi;
    private readonly IFeishuV3UserApi _userApi;
    private readonly ITokenManager _tokenManager;

    public OrganizationService(
        IFeishuV3DepartmentsApi departmentsApi,
        IFeishuV3UserApi userApi,
        ITokenManager tokenManager)
    {
        _departmentsApi = departmentsApi;
        _userApi = userApi;
        _tokenManager = tokenManager;
    }

    public async Task<string> CreateDepartmentAsync(string departmentName, string parentId)
    {
        var token = await _tokenManager.GetTokenAsync();
        var request = new DepartmentCreateRequest
        {
            Name = departmentName,
            ParentDepartmentId = parentId
        };

        var result = await _departmentsApi.CreateDepartmentAsync(token, request);
        return result.Data.Department.Id;
    }
}

部门管理详解

部门是组织架构的基本单位,在飞书平台中扮演着重要角色。通过部门管理,我们可以构建清晰的组织架构,便于人员管理和权限控制。

创建部门

创建部门是组织管理的基础操作之一。飞书提供了完整的部门创建接口,支持设置部门名称、父部门、负责人等信息。

csharp 复制代码
/// <summary>
/// 创建部门示例
/// </summary>
[HttpPost("departments")]
public async Task<IActionResult> CreateDepartment([FromBody] DepartmentCreateRequest request)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        var result = await _departmentsApi.CreateDepartmentAsync(token, request);
        
        if (result.Success)
        {
            return Ok(new { Id = result.Data.Department.Id, Message = "部门创建成功" });
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

更新部门信息

随着组织发展,部门信息可能会发生变化,这时我们需要更新部门信息:

csharp 复制代码
/// <summary>
/// 更新部门信息示例
/// </summary>
[HttpPut("departments/{departmentId}")]
public async Task<IActionResult> UpdateDepartment(string departmentId, [FromBody] DepartmentUpdateRequest request)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        var result = await _departmentsApi.UpdateDepartmentAsync(token, departmentId, request);
        
        if (result.Success)
        {
            return Ok(new { Message = "部门信息更新成功" });
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

获取部门信息

获取部门信息是日常管理中最频繁的操作之一:

csharp 复制代码
/// <summary>
/// 获取部门信息示例
/// </summary>
[HttpGet("departments/{departmentId}")]
public async Task<IActionResult> GetDepartment(string departmentId)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        var result = await _departmentsApi.GetDepartmentInfoByIdAsync(token, departmentId);
        
        if (result.Success)
        {
            return Ok(result.Data.Department);
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

获取子部门列表

获取某个部门下的所有子部门:

csharp 复制代码
/// <summary>
/// 获取子部门列表示例
/// </summary>
[HttpGet("departments/{departmentId}/children")]
public async Task<IActionResult> GetSubDepartments(string departmentId, bool fetchChild = false)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        var result = await _departmentsApi.GetDepartmentsByParentIdAsync(
            token, 
            departmentId, 
            fetchChild: fetchChild);
        
        if (result.Success)
        {
            return Ok(result.Data.Departments);
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

用户管理详解

用户是组织中的基本元素,用户管理是组织管理的核心组成部分。飞书提供了完善的用户管理API,支持用户的创建、更新、查询、删除等操作。

创建用户

创建用户是用户管理中最基础的操作之一:

csharp 复制代码
/// <summary>
/// 创建用户示例
/// </summary>
[HttpPost("users")]
public async Task<IActionResult> CreateUser([FromBody] CreateUserRequest request)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        // 生成唯一的客户端令牌以防重复提交
        var clientToken = Guid.NewGuid().ToString();
        
        var result = await _userApi.CreateUserAsync(
            token, 
            request, 
            client_token: clientToken);
        
        if (result.Success)
        {
            return Ok(new { UserId = result.Data.User.UserId, Message = "用户创建成功" });
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

更新用户信息

更新用户信息以反映员工状态变化:

csharp 复制代码
/// <summary>
/// 更新用户信息示例
/// </summary>
[HttpPut("users/{userId}")]
public async Task<IActionResult> UpdateUser(string userId, [FromBody] UpdateUserRequest request)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        var result = await _userApi.UpdateUser_Tenant_Async(token, userId, request);
        
        if (result.Success)
        {
            return Ok(new { Message = "用户信息更新成功" });
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

查询用户信息

获取特定用户的信息:

csharp 复制代码
/// <summary>
/// 获取用户信息示例
/// </summary>
[HttpGet("users/{userId}")]
public async Task<IActionResult> GetUser(string userId)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        var result = await _userApi.GetUserInfoById_Tenant_Async(token, userId);
        
        if (result.Success)
        {
            return Ok(result.Data.User);
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

删除用户

当员工离职时,需要将其从组织架构中移除:

csharp 复制代码
/// <summary>
/// 删除用户示例
/// </summary>
[HttpDelete("users/{userId}")]
public async Task<IActionResult> DeleteUser(string userId, [FromBody] DeleteSettingsRequest request)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        var result = await _userApi.DeleteUserByIdAsync(token, userId, request);
        
        if (result.Success)
        {
            return Ok(new { Message = "用户删除成功" });
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

用户角色管理详解

角色管理是权限控制系统的重要组成部分。通过为用户分配不同的角色,可以实现细粒度的权限控制。

创建角色

创建一个新的角色:

csharp 复制代码
/// <summary>
/// 创建角色示例
/// </summary>
[HttpPost("roles")]
public async Task<IActionResult> CreateRole([FromBody] RoleRequest request)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        var result = await _roleApi.CreateRoleAsync(token, request);
        
        if (result.Success)
        {
            return Ok(new { RoleId = result.Data.Role.Id, Message = "角色创建成功" });
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

更新角色

更新角色信息:

csharp 复制代码
/// <summary>
/// 更新角色示例
/// </summary>
[HttpPut("roles/{roleId}")]
public async Task<IActionResult> UpdateRole(string roleId, [FromBody] RoleRequest request)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        var result = await _roleApi.UpdateRoleAsync(token, roleId, request);
        
        if (result.Success)
        {
            return Ok(new { Message = "角色更新成功" });
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

删除角色

删除不再需要的角色:

csharp 复制代码
/// <summary>
/// 删除角色示例
/// </summary>
[HttpDelete("roles/{roleId}")]
public async Task<IActionResult> DeleteRole(string roleId)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        var result = await _roleApi.DeleteRoleByIdAsync(token, roleId);
        
        if (result.Success)
        {
            return Ok(new { Message = "角色删除成功" });
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

职级管理详解

职级是组织中表示员工层级关系的重要概念,通过职级管理可以建立清晰的晋升通道。

创建职级

创建新的职级:

csharp 复制代码
/// <summary>
/// 创建职级示例
/// </summary>
[HttpPost("joblevels")]
public async Task<IActionResult> CreateJobLevel([FromBody] JobLevelCreateUpdateRequest request)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        var result = await _jobLevelApi.CreateJobLevelAsync(token, request);
        
        if (result.Success)
        {
            return Ok(new { JobLevelId = result.Data.JobLevel.Id, Message = "职级创建成功" });
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

更新职级

更新职级信息:

csharp 复制代码
/// <summary>
/// 更新职级示例
/// </summary>
[HttpPut("joblevels/{jobLevelId}")]
public async Task<IActionResult> UpdateJobLevel(string jobLevelId, [FromBody] JobLevelCreateUpdateRequest request)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        var result = await _jobLevelApi.UpdateJobLevelAsync(token, jobLevelId, request);
        
        if (result.Success)
        {
            return Ok(new { Message = "职级更新成功" });
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

获取职级信息

获取特定职级的信息:

csharp 复制代码
/// <summary>
/// 获取职级信息示例
/// </summary>
[HttpGet("joblevels/{jobLevelId}")]
public async Task<IActionResult> GetJobLevel(string jobLevelId)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        var result = await _jobLevelApi.GetJobLevelByIdAsync(token, jobLevelId);
        
        if (result.Success)
        {
            return Ok(result.Data.JobLevel);
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

删除职级

删除不再使用的职级:

csharp 复制代码
/// <summary>
/// 删除职级示例
/// </summary>
[HttpDelete("joblevels/{jobLevelId}")]
public async Task<IActionResult> DeleteJobLevel(string jobLevelId)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        var result = await _jobLevelApi.DeleteJobLevelByIdAsync(token, jobLevelId);
        
        if (result.Success)
        {
            return Ok(new { Message = "职级删除成功" });
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

职位管理详解

职位是对员工在组织中承担的具体工作的描述,通过职位管理可以明确员工职责。

获取职位列表

获取当前租户下的职位列表:

csharp 复制代码
/// <summary>
/// 获取职位列表示例
/// </summary>
[HttpGet("jobtitles")]
public async Task<IActionResult> GetJobTitles(int pageSize = 10, string? pageToken = null)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        var result = await _jobTitleApi.GetTenantJobTitlesListAsync(token, pageSize, pageToken);
        
        if (result.Success)
        {
            return Ok(result.Data.JobTitles);
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

获取特定职位信息

获取特定职位的详细信息:

csharp 复制代码
/// <summary>
/// 获取职位信息示例
/// </summary>
[HttpGet("jobtitles/{jobTitleId}")]
public async Task<IActionResult> GetJobTitle(string jobTitleId)
{
    try
    {
        var token = await _tokenManager.GetTokenAsync();
        var result = await _jobTitleApi.GetTenantJobTitleByIdAsync(token, jobTitleId);
        
        if (result.Success)
        {
            return Ok(result.Data.JobTitle);
        }
        
        return BadRequest(new { Error = result.Message });
    }
    catch (Exception ex)
    {
        return BadRequest(new { Error = ex.Message });
    }
}

完整示例

以下是一个综合性的、贴近真实场景的代码示例,展示如何使用Mud.Feishu组件进行完整的组织管理操作:

csharp 复制代码
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Mud.Feishu;
using Mud.Feishu.DataModels.Departments.RequestModel;
using Mud.Feishu.DataModels.Employees.RequestModel;
using Mud.Feishu.DataModels.JobLevel;
using Mud.Feishu.DataModels.Roles;
using Mud.Feishu.DataModels.Users;

/// <summary>
/// 组织管理综合示例
/// 演示如何使用Mud.Feishu进行完整的组织管理操作
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class OrganizationManagementController : ControllerBase
{
    private readonly IFeishuV3DepartmentsApi _departmentsApi;
    private readonly IFeishuV3UserApi _userApi;
    private readonly IFeishuV3RoleApi _roleApi;
    private readonly IFeishuV3JobLevelApi _jobLevelApi;
    private readonly IFeishuV3JobTitleApi _jobTitleApi;
    private readonly ITokenManager _tokenManager;

    public OrganizationManagementController(
        IFeishuV3DepartmentsApi departmentsApi,
        IFeishuV3UserApi userApi,
        IFeishuV3RoleApi roleApi,
        IFeishuV3JobLevelApi jobLevelApi,
        IFeishuV3JobTitleApi jobTitleApi,
        ITokenManager tokenManager)
    {
        _departmentsApi = departmentsApi;
        _userApi = userApi;
        _roleApi = roleApi;
        _jobLevelApi = jobLevelApi;
        _jobTitleApi = jobTitleApi;
        _tokenManager = tokenManager;
    }

    /// <summary>
    /// 初始化组织架构示例
    /// 创建部门、职位、职级、角色等基础数据
    /// </summary>
    [HttpPost("initialize")]
    public async Task<IActionResult> InitializeOrganization()
    {
        try
        {
            var token = await _tokenManager.GetTokenAsync();
            
            // 1. 创建根部门 - 公司
            var companyRequest = new DepartmentCreateRequest
            {
                Name = "某某科技有限公司",
                ParentDepartmentId = "0", // 根部门
                LeaderUserId = ""
            };
            
            var companyResult = await _departmentsApi.CreateDepartmentAsync(token, companyRequest);
            if (!companyResult.Success)
            {
                return BadRequest(new { Error = $"创建公司部门失败: {companyResult.Message}" });
            }
            
            var companyId = companyResult.Data.Department.Id;
            
            // 2. 创建子部门
            var departments = new[]
            {
                new { Name = "技术部", ParentId = companyId },
                new { Name = "产品部", ParentId = companyId },
                new { Name = "市场部", ParentId = companyId },
                new { Name = "人事部", ParentId = companyId }
            };
            
            var departmentIds = new Dictionary<string, string>();
            
            foreach (var dept in departments)
            {
                var deptRequest = new DepartmentCreateRequest
                {
                    Name = dept.Name,
                    ParentDepartmentId = dept.ParentId
                };
                
                var deptResult = await _departmentsApi.CreateDepartmentAsync(token, deptRequest);
                if (deptResult.Success)
                {
                    departmentIds[dept.Name] = deptResult.Data.Department.Id;
                }
                else
                {
                    return BadRequest(new { Error = $"创建部门 {dept.Name} 失败: {deptResult.Message}" });
                }
            }
            
            // 3. 创建职级
            var jobLevels = new[]
            {
                new { Name = "初级工程师", Level = 1 },
                new { Name = "中级工程师", Level = 2 },
                new { Name = "高级工程师", Level = 3 },
                new { Name = "技术专家", Level = 4 },
                new { Name = "首席技术官", Level = 5 }
            };
            
            var jobLevelIds = new Dictionary<string, string>();
            
            foreach (var jl in jobLevels)
            {
                var jobLevelRequest = new JobLevelCreateUpdateRequest
                {
                    Name = jl.Name,
                    Level = jl.Level,
                    Description = $"{jl.Name}职级描述"
                };
                
                var jobLevelResult = await _jobLevelApi.CreateJobLevelAsync(token, jobLevelRequest);
                if (jobLevelResult.Success)
                {
                    jobLevelIds[jl.Name] = jobLevelResult.Data.JobLevel.Id;
                }
                else
                {
                    return BadRequest(new { Error = $"创建职级 {jl.Name} 失败: {jobLevelResult.Message}" });
                }
            }
            
            // 4. 创建角色
            var roles = new[]
            {
                new { Name = "管理员", Description = "系统管理员" },
                new { Name = "部门经理", Description = "部门负责人" },
                new { Name = "普通员工", Description = "一般员工" }
            };
            
            var roleIds = new Dictionary<string, string>();
            
            foreach (var r in roles)
            {
                var roleRequest = new RoleRequest
                {
                    RoleName = r.Name,
                    DisplayName = r.Description
                };
                
                var roleResult = await _roleApi.CreateRoleAsync(token, roleRequest);
                if (roleResult.Success)
                {
                    roleIds[r.Name] = roleResult.Data.Role.Id;
                }
                else
                {
                    return BadRequest(new { Error = $"创建角色 {r.Name} 失败: {roleResult.Message}" });
                }
            }
            
            // 5. 创建一些示例用户
            var users = new[]
            {
                new { Name = "张三", Department = "技术部", JobLevel = "高级工程师", Role = "管理员", Mobile = "13800138001" },
                new { Name = "李四", Department = "产品部", JobLevel = "中级工程师", Role = "部门经理", Mobile = "13800138002" },
                new { Name = "王五", Department = "市场部", JobLevel = "初级工程师", Role = "普通员工", Mobile = "13800138003" }
            };
            
            foreach (var u in users)
            {
                var userRequest = new CreateUserRequest
                {
                    Name = u.Name,
                    Mobile = u.Mobile,
                    DepartmentIds = new List<string> { departmentIds[u.Department] },
                    JobLevelId = jobLevelIds[u.JobLevel],
                    EmployeeType = 1 // 正式员工
                };
                
                var clientToken = Guid.NewGuid().ToString();
                var userResult = await _userApi.CreateUserAsync(token, userRequest, client_token: clientToken);
                if (!userResult.Success)
                {
                    return BadRequest(new { Error = $"创建用户 {u.Name} 失败: {userResult.Message}" });
                }
            }
            
            return Ok(new 
            { 
                Message = "组织架构初始化成功",
                Departments = departmentIds,
                JobLevels = jobLevelIds,
                Roles = roleIds
            });
        }
        catch (Exception ex)
        {
            return BadRequest(new { Error = $"初始化组织架构时发生错误: {ex.Message}" });
        }
    }

    /// <summary>
    /// 添加新员工示例
    /// </summary>
    [HttpPost("employees")]
    public async Task<IActionResult> AddEmployee([FromBody] EmployeeCreateRequest request)
    {
        try
        {
            var token = await _tokenManager.GetTokenAsync();
            
            // 创建用户
            var userRequest = new CreateUserRequest
            {
                Name = request.Name,
                Mobile = request.Mobile,
                Email = request.Email,
                DepartmentIds = request.DepartmentIds,
                JobLevelId = request.JobLevelId,
                EmployeeType = request.EmployeeType,
                JoinTime = request.JoinTime
            };
            
            var clientToken = Guid.NewGuid().ToString();
            var userResult = await _userApi.CreateUserAsync(token, userRequest, client_token: clientToken);
            
            if (userResult.Success)
            {
                return Ok(new 
                { 
                    UserId = userResult.Data.User.UserId, 
                    Message = "员工添加成功" 
                });
            }
            
            return BadRequest(new { Error = $"添加员工失败: {userResult.Message}" });
        }
        catch (Exception ex)
        {
            return BadRequest(new { Error = $"添加员工时发生错误: {ex.Message}" });
        }
    }

    /// <summary>
    /// 获取组织架构树示例
    /// </summary>
    [HttpGet("structure")]
    public async Task<IActionResult> GetOrganizationStructure()
    {
        try
        {
            var token = await _tokenManager.GetTokenAsync();
            
            // 获取根部门
            var rootDepartments = await _departmentsApi.GetDepartmentsByParentIdAsync(token, "0");
            if (!rootDepartments.Success)
            {
                return BadRequest(new { Error = $"获取根部门失败: {rootDepartments.Message}" });
            }
            
            var structure = new List<object>();
            
            foreach (var rootDept in rootDepartments.Data.Departments)
            {
                var deptStructure = await BuildDepartmentStructure(token, rootDept.Id);
                structure.Add(deptStructure);
            }
            
            return Ok(structure);
        }
        catch (Exception ex)
        {
            return BadRequest(new { Error = $"获取组织架构时发生错误: {ex.Message}" });
        }
    }
    
    /// <summary>
    /// 递归构建部门结构树
    /// </summary>
    private async Task<object> BuildDepartmentStructure(string token, string departmentId)
    {
        var deptInfo = await _departmentsApi.GetDepartmentInfoByIdAsync(token, departmentId);
        if (!deptInfo.Success)
        {
            return new { Error = $"获取部门信息失败: {deptInfo.Message}" };
        }
        
        var dept = deptInfo.Data.Department;
        
        // 获取子部门
        var childDepts = await _departmentsApi.GetDepartmentsByParentIdAsync(token, departmentId, fetchChild: false);
        var children = new List<object>();
        
        if (childDepts.Success)
        {
            foreach (var child in childDepts.Data.Departments)
            {
                var childStructure = await BuildDepartmentStructure(token, child.Id);
                children.Add(childStructure);
            }
        }
        
        // 获取部门成员
        var members = await _userApi.GetUserByDepartmentId_Tenant_Async(token, departmentId);
        var memberList = new List<object>();
        
        if (members.Success)
        {
            foreach (var member in members.Data.Items)
            {
                memberList.Add(new 
                {
                    UserId = member.UserId,
                    Name = member.Name,
                    Mobile = member.Mobile
                });
            }
        }
        
        return new 
        {
            Id = dept.Id,
            Name = dept.Name,
            Children = children,
            Members = memberList
        };
    }
}

使用示例

csharp 复制代码
// 在Program.cs中注册服务
var builder = WebApplication.CreateBuilder(args);

// 添加控制器
builder.Services.AddControllers();

// 添加飞书服务
builder.Services.AddFeishuApiService("Feishu")
                .AddLogging(option => option.AddConsole());

// 注册Swagger(仅用于演示)
builder.Services.AddSwaggerGen();

var app = builder.Build();

// 配置管道
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

配置文件示例

json 复制代码
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Feishu": {
    "AppId": "your_feishu_app_id",
    "AppSecret": "your_feishu_app_secret",
    "BaseUrl": "https://open.feishu.cn"
  }
}

最佳实践

安全性考虑

  1. 令牌管理: 妥善保管访问令牌,避免泄露
  2. 权限控制: 遵循最小权限原则,只授予必要的操作权限
  3. 审计日志: 记录所有组织管理操作,便于追踪和审计

错误处理

csharp 复制代码
try 
{
    var result = await feishuUserApi.CreateUserAsync(token, userRequest);
    if (!result.Success) 
    {
        // 处理API错误
        Console.WriteLine($"创建用户失败: {result.Message}");
    }
}
catch (FeishuException ex)
{
    // 处理飞书特定异常
    Console.WriteLine($"飞书API异常: {ex.Message}");
}
catch (Exception ex)
{
    // 处理其他异常
    Console.WriteLine($"未知异常: {ex.Message}");
}

批量操作优化

对于大量组织操作,应该采用批量处理方式以提高效率:

csharp 复制代码
// 批量获取用户信息示例
var userIds = new[] { "user1", "user2", "user3" };
var batchResult = await feishuUserApi.GetUserByIds_Tenant_Async(token, userIds);

foreach (var userInfo in batchResult.Data.Users)
{
    // 处理每个用户信息
    ProcessUserInfo(userInfo);
}

数据验证

在执行组织管理操作前,应对输入数据进行充分验证:

csharp 复制代码
public class OrganizationValidator
{
    public static bool ValidateDepartment(DepartmentCreateRequest department)
    {
        // 验证必要字段
        if (string.IsNullOrEmpty(department.Name))
            throw new ArgumentException("部门名称不能为空");
            
        // 验证父部门ID
        if (string.IsNullOrEmpty(department.ParentDepartmentId))
            throw new ArgumentException("父部门ID不能为空");
            
        return true;
    }
    
    public static bool ValidateUser(CreateUserRequest user)
    {
        // 验证必要字段
        if (string.IsNullOrEmpty(user.Name))
            throw new ArgumentException("用户名不能为空");
            
        // 验证手机号或邮箱
        if (string.IsNullOrEmpty(user.Mobile) && string.IsNullOrEmpty(user.Email))
            throw new ArgumentException("手机号和邮箱至少需要填写一项");
            
        // 验证部门ID
        if (user.DepartmentIds == null || user.DepartmentIds.Count == 0)
            throw new ArgumentException("用户必须至少属于一个部门");
            
        return true;
    }
}

附录

A. 相关资源

B. 版本

Mud.Feishu 版本 .NET 版本 飞书 API 版本 发布日期
1.0.0 .NET 8.0/9.0/10.0 v3 2025-11-19
相关推荐
小熊熊知识库5 小时前
C#接入AI操作步骤详解(deepseek接入)
人工智能·flask·c#
玖笙&5 小时前
✨WPF编程进阶【7.3】集成动画(附源码)
c++·c#·wpf·visual studio
yue0087 小时前
C# 窗体渐变色
开发语言·javascript·c#
czhc11400756637 小时前
C#1119记录 类 string.Split type.TryParse(String,out type 变量)
android·c#
WangMing_X9 小时前
C#一个项目实现文件目录常用操作(附源码完整)
开发语言·c#
玩泥巴的10 小时前
.NET项目中如何快速的集成飞书API
c#·.net·飞书
初九之潜龙勿用10 小时前
C# 使用豆包 AI 模型实现首尾帧模式的视频生成
人工智能·microsoft·c#·ai编程·视频·ai模型·豆包
烛阴11 小时前
C#运算符与表达式终极指南:从入门到精通的万字长文
前端·c#
Crazy Struggle11 小时前
开源 .NET 工作流引擎 + 可视化设计,轻松搞定 OA/CRM/ERP 开发
.net·工作流