首页 > 人工智能 > 深度学习 > .NET 传统信息系统无缝集成飞书审批流
本文将带你走一条渐进式改造之路:保持 .NET 系统作为业务核心,将飞书审批作为移动门户,通过 API 实现无缝协同。从原理、设计到编码,完整呈现如何让传统系统焕发新生,实现移动化、实时化的现代化升级。
无论你是开发者、架构师还是技术管理者,都能收获一套可落地、可扩展的集成方案和直接复用的代码实践。
传统 .NET 系统的局限
许多企业拥有多年累积的 .NET 业务系统,这些系统在企业运营中扮演着核心角色。然而,随着移动办公和现代协同工具的普及,这些传统系统正面临着严峻的挑战:
| 痛点 | 具体表现 | 业务影响 |
|---|---|---|
| 审批流程封闭 | 审批只能在桌面端完成,无法随时随地处理 | 移动办公受阻,响应迟缓 |
| 通知方式滞后 | 依赖邮件或站内消息推送 | 审批人及时性差,流程延误 |
| 数据孤岛严重 | 审批数据与业务数据分离 | 无法形成完整的业务闭环 |
| 用户体验陈旧 | 界面风格陈旧,交互体验差 | 用户满意度低,使用意愿下降 |
飞书审批的赋能价值
飞书审批作为企业级的审批协作平台,为我们提供了一个理想的"流程协作中心":
飞书审批平台
移动优先
即时强通知
流程可视化
完善审计日志
随时随地处理审批
App推送/短信提醒
拖拽式流程配置
完整操作痕迹追溯
我们的核心目标
通过本文的实践,我们将建立 ".NET 系统为业务核心,飞书审批为流程门户" 的现代化混合架构:
架构愿景:将飞书审批作为统一的移动审批门户,保持 .NET 系统作为业务逻辑和数据存储的核心,通过 API 实时同步,形成优势互补的协同体系。
飞书审批与 .NET 系统的集成是一个 双向数据流的过程:
当用户在 .NET 系统发起审批时,系统会:
CreateInstanceAsync 创建审批实例instance_code,持久化到关联表当审批人在飞书 App 完成审批后:
instance_code 和
status审批定义是审批流程的"蓝图",在飞书管理后台配置:
// 示例:请假审批的审批定义var approvalCode = "7C468A54-8745-2245-9675-08B7C63E7A85";
定义包含:
审批实例是依据审批定义发起的一次具体审批任务:
// 创建审批实例时返回public record CreateInstancesResult{ /// <summary>
/// 审批实例 Code
/// </summary>
[JsonPropertyName("instance_code")] public string InstanceCode { get; set; } = string.Empty;
}
关键属性:
实现 .NET 系统用户与飞书用户的关联:
映射关系
通过飞书App审批
回调instance_code
.NET系统用户
UserId: 1001
飞书用户
OpenId: ou_3cda9c...
审批完成
实现方式:
FeishuOpenId 字段open_idopen_id 指定审批发起人| 层次 | 技术选型 | 说明 |
|---|---|---|
| 应用框架 | .NET 6/8/10 | 长期支持版本,性能优异 |
| 飞书 SDK | Mud.Feishu | 高度封装的飞书 API 客户端 |
| Webhook 处理 | Mud.Feishu.Webhook | 飞书事件回调处理组件 |
| 认证授权 | ASP.NET Core Identity / JWT | 内部系统身份管理 |
| 异步解耦 | RabbitMQ / Hangfire | 回调消息队列处理,提升可靠性 |
| 数据存储 | SQL Server / PostgreSQL | 业务数据 + 审批关联表 |
基础设施层
领域层 (业务逻辑)
应用层 (API)
表示层 (UI)
Web 前端 / 移动端
LeaveController
FeishuWebhookController
ILeaveService
ApprovalIntegrationService
IApprovalService
Mud.Feishu HTTP客户端
Mud.Feishu.Webhook处理器
数据仓储
EF Core
在领域层引入
IApprovalService 接口,将飞书集成细节与核心业务逻辑解耦:
/// <summary>/// 审批服务抽象接口 - 解耦飞书实现细节/// </summary>public interface IApprovalService{ /// <summary>
/// 发起审批
/// </summary>
Task<string> CreateApprovalAsync(ApprovalRequest request); /// <summary>
/// 处理审批结果回调
/// </summary>
Task HandleApprovalCallbackAsync(ApprovalCallbackEvent callbackEvent);
}/// <summary>/// 飞书审批服务实现///gov.www.yc.jrzb2.info </summary>public class FeishuApprovalService : IApprovalService{ private readonly IFeishuTenantV4Approval _approvalApi; private readonly IApprovalRecordRepository _repository; public FeishuApprovalService(
IFeishuTenantV4Approval approvalApi,
IApprovalRecordRepository repository)
{
_approvalApi = approvalApi;
_repository = repository;
} public async Task<string> CreateApprovalAsync(ApprovalRequest request)
{ // 调用飞书 API
var result = await _approvalApi.CreateInstanceAsync(...); return result.Data?.InstanceCode ?? string.Empty;
}
}
优势:
登录飞书开放平台( https://open.feishu.cn),进入应用管理:
创建自建应用
获取App ID
获取App Secret
配置到.NET系统
关键配置:
App ID 和
App Secretapproval:approval:read,
approval:instance:read,
approval:instance:create)在飞书管理后台创建"请假审批"模板:
审批定义配置
表单设置
流程设置
权限设置
请假类型
开始时间
结束时间
请假天数
请假事由
直属主管审批
→ 人事审批
全员可发起
记录关键信息:
approval_code:审批定义的唯一标识id:用于程序填充表单数据在飞书开放平台配置 Webhook:
| 配置项 | 值 |
|---|---|
| 请求网址 |
https://your-domain.com/api/feishu/webhook |
| 验证 Token |
your_verification_token(自定义) |
| 加密 Key |
your_encrypt_key(自定义) |
| 订阅事件 |
approval_instance(审批实例状态变更) |
基于
MudFeishu SDK 封装审批服务:
/// <summary>/// 飞书审批服务封装/// </summary>public class FeishuApprovalClient{ private readonly IFeishuTenantV4Approval _approvalApi; private readonly ILogger<FeishuApprovalClient> _logger; public FeishuApprovalClient(
IFeishuTenantV4Approval approvalApi,
ILogger<FeishuApprovalClient> logger)
{
_approvalApi = approvalApi;
_logger = logger;
} /// <summary>
/// 创建审批实例
/// </summary>
public async Task<string> CreateInstanceAsync(CreateInstanceRequest request)
{ var result = await _approvalApi.CreateInstanceAsync(request); if (result == null || result.Code != 0)
{
_logger.LogError("创建审批实例失败: {Msg}", result?.Msg); throw new InvalidOperationException($"创建审批实例失败: {result?.Msg}");
}
_logger.LogInformation("创建审批实例成功: {InstanceCode}", result.Data?.InstanceCode); return result.Data?.InstanceCode ?? string.Empty;
} /// <summary>
/// 获取审批实例详情
/// </summary>
public async Task<GetApprovalInstanceResult?> GetInstanceAsync(string instanceCode)
{ var result = await _approvalApi.GetInstanceByIdAsync(instanceCode); if (result == null || result.Code != 0)
{
_logger.LogError("获取审批实例失败: {Msg}", result?.Msg); return null;
} return result.Data;soccer.xj.zuq8.info
}
}
在业务数据库中添加审批关联表:
-- 审批关联表CREATE TABLE ApprovalRecords ( Id BIGINT PRIMARY KEY IDENTITY(1,1), BusinessType NVARCHAR(50) NOT NULL, -- 业务类型:LeaveRequest, PurchaseRequest... BusinessId BIGINT NOT NULL, -- 业务ID InstanceCode NVARCHAR(64) NOT NULL, -- 飞书审批实例Code ApprovalCode NVARCHAR(64) NOT NULL, -- 审批定义Code Status NVARCHAR(20) NOT NULL, -- 状态:PENDING, APPROVED, REJECTED... CallbackData NVARCHAR(MAX), -- 回调数据(JSON) CreatedTime DATETIME2 NOT NULL DEFAULT GETUTCDATE(), UpdatedTime DATETIME2 NOT NULL DEFAULT GETUTCDATE(), CONSTRAINT UK_ApprovalRecords_Business UNIQUE(BusinessType, BusinessId) );CREATE INDEX IX_ApprovalRecords_InstanceCode ON ApprovalRecords(InstanceCode);CREATE INDEX IX_ApprovalRecords_Status ON ApprovalRecords(Status);
对应的实体类:
/// <summary>/// 审批关联记录/// </summary>public class ApprovalRecord{ public long Id { get; set; } public string BusinessType { get; set; } = string.Empty; // "LeaveRequest"
public long BusinessId { get; set; } // 请假申请ID
public string InstanceCode { get; set; } = string.Empty; // 飞书实例Code
public string ApprovalCode { get; set; } = string.Empty; // 审批定义Code
public string Status { get; set; } = string.Empty; // PENDING/APPROVED/REJECTED
public string? CallbackData { get; set; } // JSON格式
public DateTime CreatedTime { get; set; } public DateTime UpdatedTime { get; set; }
}
流程图:
代码实现:
/// <summary>/// 请假服务/// </summary>public class LeaveService{ private readonly ILeaveRequestRepository _leaveRepo; private readonly IApprovalRecordRepository _approvalRepo; private readonly FeishuApprovalClient _feishuClient; private readonly ILogger<LeaveService> _logger; public LeaveService(
ILeaveRequestRepository leaveRepo,
IApprovalRecordRepository approvalRepo,
FeishuApprovalClient feishuClient,
ILogger<LeaveService> logger)
{
_leaveRepo = leaveRepo;
_approvalRepo = approvalRepo;
_feishuClient = feishuClient;
_logger = logger;
} /// <summary>
/// 提交请假申请并发起审批
/// </summary>
public async Task<long> SubmitLeaveRequestAsync(SubmitLeaveRequestDto dto)
{ // 1. 保存请假业务数据
var leaveRequest = new LeaveRequest
{
UserId = dto.UserId,gov.
LeaveType = dto.LeaveType,
StartTime = dto.StartTime,
EndTime = dto.EndTime,
Days = dto.Days,
Reason = dto.Reason,
Status = LeaveStatus.Pending, // 审批中
CreatedTime = DateTime.UtcNow
}; await _leaveRepo.AddAsync(leaveRequest); await _leaveRepo.SaveChangesAsync(); // 2. 构造飞书审批表单数据
var form = new List<object>
{ new { id = "leave_type", type = "select", value = dto.LeaveType }, new { id = "start_time", type = "date", value = dto.StartTime.ToString("yyyy-MM-dd") }, new { id = "end_time", type = "date", value = dto.EndTime.ToString("yyyy-MM-dd") }, new { id = "days", type = "number", value = dto.Days.ToString() }, new { id = "reason", type = "textarea", value = dto.Reason }
}; // 3. 调用飞书API创建审批实例
var request = new CreateInstanceRequest
{
ApprovalCode = "7C468A54-8745-2245-9675-08B7C63E7A85", // 请假审批定义Code
UserId = dto.FeishuUserId, // 飞书用户ID
Form = JsonSerializer.Serialize(form),
Uuid = Guid.NewGuid().ToString() // 幂等ID
}; string instanceCode; try
{
instanceCode = await _feishuClient.CreateInstanceAsync(request);
} catch (Exception ex)
{
_logger.LogError(ex, "创建飞书审批实例失败"); // 回滚业务数据
leaveRequest.Status = LeaveStatus.Failed; await _leaveRepo.SaveChangesAsync(); throw;
} // 4. 保存审批关联记录
var approvalRecord = new ApprovalRecord
{
BusinessType = "LeaveRequest",
BusinessId = leaveRequest.Id,
InstanceCode = instanceCode,
ApprovalCode = request.ApprovalCode,
Status = "PENDING",blog.fovkj.com
CreatedTime = DateTime.UtcNow,
UpdatedTime = DateTime.UtcNow
}; await _approvalRepo.AddAsync(approvalRecord); await _approvalRepo.SaveChangesAsync();
_logger.LogInformation("请假申请已提交并创建审批: LeaveId={LeaveId}, InstanceCode={InstanceCode}",
leaveRequest.Id, instanceCode); return leaveRequest.Id;
}
}
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048957/viewspace-3107306/ ,如需转载,请注明出处,否则将追究法律责任。