ProjectManagement 域统一了项目管理平台的项目与任务管理能力。Asana 和 Teambition 两家供应商共享同一个 IProjectManagementService 接口,但鉴权机制与数据封装差异显著:Asana 用 Bearer Personal Access Token 配合 data 封装,Teambition 用 AppKey + AppSecret 换 access_token 后以 query 参数注入。
域结构
Bitzsoft.Integrations.ProjectManagement ← 抽象层├── Bitzsoft.Integrations.ProjectManagement.Asana ← Asana(Bearer PAT)├── Bitzsoft.Integrations.ProjectManagement.Teambition ← Teambition(AppKey+AppSecret → access_token query)└── Bitzsoft.Integrations.ProjectManagement.All ← 聚合包标准三层包模式。
统一接口(7 方法)
IProjectManagementService 围绕”项目(Project)“和”任务(Task)“两个核心概念组织,共 7 个方法:
public interface IProjectManagementService{ string ProviderName { get; }
// 项目(2) Task<ProjectInfo> CreateProjectAsync(CreateProjectRequest request, CancellationToken cancellationToken = default); Task<List<ProjectInfo>> ListProjectsAsync(ListProjectsRequest request, CancellationToken cancellationToken = default);
// 任务 CRUD + 完成 + 列表(5) Task<TaskInfo> CreateTaskAsync(CreateTaskRequest request, CancellationToken cancellationToken = default); Task<TaskInfo> UpdateTaskAsync(string taskId, UpdateTaskRequest request, CancellationToken cancellationToken = default); Task DeleteTaskAsync(string taskId, CancellationToken cancellationToken = default); Task<TaskInfo> CompleteTaskAsync(string taskId, CancellationToken cancellationToken = default); Task<List<TaskInfo>> ListTasksAsync(ListTasksRequest request, CancellationToken cancellationToken = default);}查询类方法(Create / Update / List)返回强类型模型,操作类方法(Delete)为无返回 Task,失败抛 ProjectManagementException。CompleteTaskAsync 把任务置为完成态,返回带终态状态的 TaskInfo。
鉴权模型
两家供应商使用截然不同的鉴权机制:
| 供应商 | 鉴权机制 | Token 注入 | 数据封装 | Token 刷新 |
|---|---|---|---|---|
| Asana | Personal Access Token(PAT) | Authorization: Bearer {pat} 头 | data 包装({ "data": {...} }) | 静态 PAT,不刷新 |
| Teambition | AppKey + AppSecret 换 access_token | query 参数 ?access_token= | 直接对象 | POST 换 token,可缓存 |
供应商清单
| 供应商 | Provider ID | API 基地址 | Stability | DI 方法 |
|---|---|---|---|---|
| Asana | asana | app.asana.com/api/1.0 | Preview | AddAsanaProjectManagement() |
| Teambition | teambition | open.teambition.com/api | Preview | AddTeambitionProjectManagement() |
Asana 是国际主流团队任务协作平台,Teambition 是阿里旗下的国内项目协作平台。
注册
单厂商
// ① Asana(Bearer PAT,data 封装)builder.Services.AddAsanaProjectManagement(builder.Configuration.GetSection("ProjectManagement:Asana"));
// ② Teambition(AppKey+AppSecret → access_token query)builder.Services.AddTeambitionProjectManagement(builder.Configuration.GetSection("ProjectManagement:Teambition"));全量聚合
builder.Services.AddBitzsoftProjectManagementAll(builder.Configuration, "ProjectManagement");按配置节存在性自动注册,appsettings.json 只需写出启用的供应商:
{ "ProjectManagement": { "Asana": { "PersonalAccessToken": "1/...", "WorkspaceId": "..." }, "Teambition": { "AppKey": "...", "AppSecret": "...", "OrgId": "..." } }}消费
创建项目与任务
public class TaskPlanner(IIntegrationProviderResolver<IProjectManagementService> providers){ public async Task<TaskInfo> PlanAsync(string vendor, string projectName, string taskName, DateTimeOffset dueDate) { var pm = providers.GetRequired(vendor); // "asana" / "teambition"
// ① 创建项目 var project = await pm.CreateProjectAsync(new CreateProjectRequest { Name = projectName, });
// ② 在项目下创建任务 return await pm.CreateTaskAsync(new CreateTaskRequest { ProjectId = project.Id, Name = taskName, DueDate = dueDate, }); }}任务更新、完成与删除
// 更新任务(改截止日期、指派人)await pm.UpdateTaskAsync(taskId, new UpdateTaskRequest{ DueDate = newDueDate, AssigneeId = "user-456",});
// 标记完成var done = await pm.CompleteTaskAsync(taskId);// done.Status: Completed
// 删除任务await pm.DeleteTaskAsync(taskId);列表查询
// 列出项目var projects = await pm.ListProjectsAsync(new ListProjectsRequest{ PageIndex = 1, PageSize = 20,});
// 列出某项目下的任务var tasks = await pm.ListTasksAsync(new ListTasksRequest{ ProjectId = project.Id, Status = TaskStatus.Open,});多厂商路由
public class PmRouter(IIntegrationProviderResolver<IProjectManagementService> providers){ public async Task<List<ProjectInfo>> ListProjectsAsync(string platform) { var pm = providers.GetRequired(platform); // "asana" / "teambition" return await pm.ListProjectsAsync(new ListProjectsRequest()); }}