接口名称
部门管理API(用户令牌)- IFeishuUserV3Departments
功能描述
飞书组织机构部门是指企业组织架构树上的某一个节点。当前接口使用用户令牌访问,适用于用户应用场景,主要提供部门信息的查询功能。在部门内部,可添加用户作为部门成员,也可添加新的部门作为子部门。用户令牌版本具有权限限制,只能查看有权限访问的部门信息。
参考文档
https://open.feishu.cn/document/server-docs/contact-v3/department/field-overview
函数列表
| 函数名称 | 功能描述 | 认证方式 | HTTP 方法 |
|---|---|---|---|
| GetDepartmentInfoByIdAsync | 获取单个部门信息 | 用户令牌 | GET |
| GetDepartmentsByIdsAsync | 批量获取部门信息 | 用户令牌 | GET |
| GetDepartmentsByParentIdAsync | 获取子部门列表 | 用户令牌 | GET |
| GetParentDepartmentsByIdAsync | 获取父部门信息 | 用户令牌 | GET |
函数详细内容
函数名称:获取单个部门信息
函数签名:
csharp
Task<FeishuApiResult<GetDepartmentInfoResult>?> GetDepartmentInfoByIdAsync(
[Path] string department_id,
[Query("user_id_type")] string? user_id_type = "open_id",
[Query("department_id_type")] string? department_id_type = "open_department_id",
CancellationToken cancellationToken = default);认证:用户令牌
参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| department_id | string | ✅ 必填 | 部门ID |
| user_id_type | string | ⚪ 可选 | 用户ID类型,默认为"open_id" |
| department_id_type | string | ⚪ 可选 | 部门ID类型,默认为"open_department_id" |
响应:
json
{
"code": 0,
"msg": "success",
"data": {
"department": {
"department_id": "od-1234567890",
"name": "技术部",
"parent_department_id": "0",
"leader_user_id": "ou_1234567890",
"leaders": [
{
"user_id": "ou_1234567890",
"leader_type": 1
}
],
"primary_member_count": 25,
"status": {
"is_deleted": false
},
"create_group_chat": true
}
}
}说明:
- 获取单个部门的详细信息,包括部门名称、ID、父部门、负责人、状态以及成员个数等
- 使用用户令牌只能获取有权限查看的部门信息
- 敏感信息(如某些字段)可能因为权限限制而不可见
代码示例:
javascript
// 获取部门详细信息
async function getDepartmentDetails(departmentId) {
const result = await feishuUserV3Departments.getDepartmentInfoByIdAsync(
departmentId,
"open_id",
"open_department_id"
);
if (result.code === 0) {
const dept = result.data.department;
console.log("=== 部门详细信息 ===");
console.log(`部门ID: ${dept.department_id}`);
console.log(`部门名称: ${dept.name}`);
console.log(`父部门ID: ${dept.parent_department_id}`);
console.log(`部门主管: ${dept.leader_user_id || '未设置'}`);
console.log(`主要成员数量: ${dept.primary_member_count}`);
console.log(`部门状态: ${dept.status.is_deleted ? '已删除' : '正常'}`);
console.log(`是否创建群聊: ${dept.create_group_chat ? '是' : '否'}`);
// 显示负责人信息
if (dept.leaders && dept.leaders.length > 0) {
console.log("\n负责人列表:");
dept.leaders.forEach((leader, index) => {
const leaderType = leader.leader_type === 1 ? "部门主管" : "部门分管";
console.log(`${index + 1}. ${leader.user_id} (${leaderType})`);
});
}
// 显示HRBP信息(如果有权限)
if (dept.department_hrbps && dept.department_hrbps.length > 0) {
console.log("\nHRBP列表:");
dept.department_hrbps.forEach((hrbp, index) => {
console.log(`${index + 1}. ${hrbp}`);
});
}
return dept;
} else {
console.error("获取部门信息失败:", result.msg);
// 权限相关的错误处理
if (result.code === 403) {
console.log("权限不足,无法查看该部门信息");
} else if (result.code === 404) {
console.log("部门不存在或已被删除");
}
return null;
}
}
// 使用示例:获取并分析部门信息
async function analyzeDepartment(departmentId) {
const dept = await getDepartmentDetails(departmentId);
if (dept) {
// 分析部门规模
if (dept.primary_member_count > 0) {
console.log(`\n=== 部门规模分析 ===`);
if (dept.primary_member_count < 10) {
console.log("小型部门(<10人)");
} else if (dept.primary_member_count < 50) {
console.log("中型部门(10-50人)");
} else {
console.log("大型部门(>50人)");
}
}
// 分析组织结构
if (dept.parent_department_id === "0") {
console.log("该部门为根部门(顶级部门)");
} else {
console.log(`该部门隶属于父部门: ${dept.parent_department_id}`);
}
}
}
analyzeDepartment("tech_dept_001");函数名称:批量获取部门信息
函数签名:
csharp
Task<FeishuApiResult<BatchGetDepartmentRequest>?> GetDepartmentsByIdsAsync(
[Query("department_ids")] string[] department_ids,
[Query("user_id_type")] string? user_id_type = "open_id",
[Query("department_id_type")] string? department_id_type = "open_department_id",
CancellationToken cancellationToken = default);认证:用户令牌
参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| department_ids | string[] | ✅ 必填 | 部门ID数组 |
| user_id_type | string | ⚪ 可选 | 用户ID类型,默认为"open_id" |
| department_id_type | string | ⚪ 可选 | 部门ID类型,默认为"open_department_id" |
响应:
json
{
"code": 0,
"msg": "success",
"data": {
"departments": [
{
"department_id": "od-1234567890",
"name": "技术部",
"parent_department_id": "0",
"primary_member_count": 25
},
{
"department_id": "od-1234567891",
"name": "产品部",
"parent_department_id": "0",
"primary_member_count": 15
}
]
}
}说明:
- 批量获取多个部门的详细信息
- 使用用户令牌只能获取有权限查看的部门
- 最多支持50个部门ID
- 无权限的部门将不会在结果中返回
代码示例:
javascript
// 批量获取部门信息
async function getBatchDepartmentInfo(departmentIds) {
if (!departmentIds || departmentIds.length === 0) {
console.log("部门ID列表不能为空");
return [];
}
const maxBatchSize = 50;
const allDepartments = [];
for (let i = 0; i < departmentIds.length; i += maxBatchSize) {
const batch = departmentIds.slice(i, i + maxBatchSize);
const result = await feishuUserV3Departments.getDepartmentsByIdsAsync(
batch,
"open_id",
"open_department_id"
);
if (result.code === 0) {
allDepartments.push(...result.data.departments);
console.log(`批次 ${Math.floor(i / maxBatchSize) + 1}: 获取到 ${result.data.departments.length} 个部门`);
} else {
console.error(`批次查询失败:`, result.msg);
if (result.code === 403) {
console.log("部分部门权限不足,已过滤");
}
}
}
return allDepartments;
}
// 分析部门成员分布和权限情况
async function analyzeAccessibleDepartments(departmentIds) {
console.log(`准备批量获取 ${departmentIds.length} 个部门信息...`);
const departments = await getBatchDepartmentInfo(departmentIds);
if (departments.length === 0) {
console.log("未获取到任何有权限的部门信息");
return;
}
const accessibleCount = departments.length;
const totalCount = departmentIds.length;
const accessRate = ((accessibleCount / totalCount) * 100).toFixed(1);
console.log(`\n=== 部门访问权限分析 ===`);
console.log(`总查询部门数: ${totalCount}`);
console.log(`有权限访问: ${accessibleCount}`);
console.log(`无权限访问: ${totalCount - accessibleCount}`);
console.log(`访问权限比例: ${accessRate}%`);
// 分析部门成员分布
const totalMembers = departments.reduce((sum, dept) => sum + (dept.primary_member_count || 0), 0);
const avgMembers = Math.round(totalMembers / departments.length);
console.log(`\n=== 成员分布统计 ===`);
console.log(`总成员数: ${totalMembers}`);
console.log(`平均部门人数: ${avgMembers}`);
// 按成员数量排序并显示
departments.sort((a, b) => (b.primary_member_count || 0) - (a.primary_member_count || 0));
console.log(`\n=== 部门详情(按人数排序) ===`);
departments.forEach((dept, index) => {
const memberCount = dept.primary_member_count || 0;
const percentage = totalMembers > 0 ? ((memberCount / totalMembers) * 100).toFixed(1) : '0.0';
const parentInfo = dept.parent_department_id === "0" ? "根部门" : `父部门: ${dept.parent_department_id}`;
console.log(`${index + 1}. ${dept.name}`);
console.log(` 人数: ${memberCount} (${percentage}%)`);
console.log(` ${parentInfo}`);
console.log(` ID: ${dept.department_id}`);
});
return departments;
}
// 使用示例:分析当前用户可访问的部门
analyzeAccessibleDepartments([
"tech_dept_001",
"product_dept_001",
"sales_dept_001",
"hr_dept_001",
"finance_dept_001"
]);函数名称:获取子部门列表
函数签名:
csharp
Task<FeishuApiPageListResult<GetDepartmentInfo>?> GetDepartmentsByParentIdAsync(
[Path] string department_id,
[Query("fetch_child")] bool fetch_child = false,
[Query("page_size")] int? page_size = 10,
[Query("page_token")] string? page_token = null,
[Query("user_id_type")] string? user_id_type = "open_id",
[Query("department_id_type")] string? department_id_type = "open_department_id",
CancellationToken cancellationToken = default);认证:用户令牌
参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| department_id | string | ✅ 必填 | 父部门ID |
| fetch_child | bool | ⚪ 可选 | 是否递归获取子部门,默认false |
| page_size | int? | ⚪ 可选 | 分页大小,默认10,最大50 |
| page_token | string | ⚪ 可选 | 分页标记,首次请求不填 |
| user_id_type | string | ⚪ 可选 | 用户ID类型,默认为"open_id" |
| department_id_type | string | ⚪ 可选 | 部门ID类型,默认为"open_department_id" |
响应:
json
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"department_id": "od-1234567891",
"name": "前端团队",
"parent_department_id": "od-1234567890",
"primary_member_count": 8,
"leader_user_id": "ou_1234567891"
}
],
"page_token": "next_page_token",
"has_more": true
}
}说明:
- 查询指定部门下的子部门列表
- 使用用户令牌只能获取有权限查看的子部门
- 支持递归查询获取所有层级的子部门
- 支持分页查询,适合获取大量子部门
代码示例:
javascript
// 获取部门的所有子部门(支持分页和递归)
async function getAllSubDepartments(parentDepartmentId, includeRecursive = false, maxDepth = 3) {
let hasMore = true;
let pageToken = null;
const allDepartments = [];
let pageCount = 0;
while (hasMore) {
pageCount++;
console.log(`正在获取第 ${pageCount} 页子部门数据...`);
const result = await feishuUserV3Departments.getDepartmentsByParentIdAsync(
parentDepartmentId,
false, // 手动控制递归
50, // 每页获取更多数据
pageToken,
"open_id",
"open_department_id"
);
if (result.code === 0) {
const departments = result.data.items;
allDepartments.push(...departments);
hasMore = result.data.has_more;
pageToken = result.data.page_token;
console.log(`第 ${pageCount} 页获取到 ${departments.length} 个子部门`);
// 如果需要递归且当前层级的子部门数量较少,获取下一级
if (includeRecursive && pageCount === 1 && departments.length < 10) {
for (const dept of departments) {
const subDepts = await getAllSubDepartments(dept.department_id, true, maxDepth - 1);
if (subDepts.length > 0) {
dept.sub_departments = subDepts;
}
}
}
} else {
console.error(`第 ${pageCount} 页获取失败:`, result.msg);
if (result.code === 403) {
console.log("权限不足,无法查看该部门的子部门");
}
break;
}
}
return allDepartments;
}
// 构建部门层级树
function buildDepartmentTree(departments, parentDepartmentId) {
const tree = [];
const children = departments.filter(dept => dept.parent_department_id === parentDepartmentId);
for (const child of children) {
const childNode = { ...child };
childNode.children = buildDepartmentTree(departments, child.department_id);
tree.push(childNode);
}
return tree;
}
// 显示部门树结构
function printDepartmentTree(nodes, indent = 0) {
const prefix = " ".repeat(indent);
nodes.forEach((node, index) => {
const isLast = index === nodes.length - 1;
const memberCount = node.primary_member_count || 0;
const leaderInfo = node.leader_user_id ? ` (主管: ${node.leader_user_id})` : "";
const connector = isLast ? "└─" : "├─";
console.log(`${prefix}${connector} ${node.name} (${memberCount}人)${leaderInfo}`);
if (node.children && node.children.length > 0) {
printDepartmentTree(node.children, indent + 1);
}
});
}
// 分析部门层级结构
async function analyzeDepartmentStructure(parentDepartmentId) {
console.log(`正在分析部门 ${parentDepartmentId} 的层级结构...`);
// 获取所有相关部门
const departments = await getAllSubDepartments(parentDepartmentId, true);
if (departments.length === 0) {
console.log("该部门下没有子部门或没有权限查看");
return;
}
console.log(`\n=== 层级结构分析 ===`);
console.log(`直接子部门数: ${departments.length}`);
// 构建树结构
const tree = buildDepartmentTree(departments, parentDepartmentId);
console.log(`\n=== 部门树结构 ===`);
printDepartmentTree(tree);
// 统计信息
const totalMembers = departments.reduce((sum, dept) => sum + (dept.primary_member_count || 0), 0);
const avgMembers = Math.round(totalMembers / departments.length);
console.log(`\n=== 统计信息 ===`);
console.log(`子部门总数: ${departments.length}`);
console.log(`子部门总人数: ${totalMembers}`);
console.log(`平均每个子部门人数: ${avgMembers}`);
// 找出最大和最小的子部门
const sortedBySize = [...departments].sort((a, b) => (b.primary_member_count || 0) - (a.primary_member_count || 0));
const largestDept = sortedBySize[0];
const smallestDept = sortedBySize[sortedBySize.length - 1];
if (largestDept && smallestDept) {
console.log(`最大子部门: ${largestDept.name} (${largestDept.primary_member_count || 0}人)`);
console.log(`最小子部门: ${smallestDept.name} (${smallestDept.primary_member_count || 0}人)`);
}
}
// 使用示例:分析技术部门的组织结构
analyzeDepartmentStructure("tech_dept_001");函数名称:获取父部门信息
函数签名:
csharp
Task<FeishuApiPageListResult<GetDepartmentInfo>?> GetParentDepartmentsByIdAsync(
[Query("department_id")] string department_id,
[Query("page_size")] int? page_size = 10,
[Query("page_token")] string? page_token = null,
[Query("user_id_type")] string? user_id_type = "open_id",
[Query("department_id_type")] string? department_id_type = "open_department_id",
CancellationToken cancellationToken = default);认证:用户令牌
参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| department_id | string | ✅ 必填 | 部门ID |
| page_size | int? | ⚪ 可选 | 分页大小,默认10,最大50 |
| page_token | string | ⚪ 可选 | 分页标记,首次请求不填 |
| user_id_type | string | ⚪ 可选 | 用户ID类型,默认为"open_id" |
| department_id_type | string | ⚪ 可选 | 部门ID类型,默认为"open_department_id" |
响应:
json
{
"code": 0,
"msg": "success",
"data": {
"items": [
{
"department_id": "od-1234567890",
"name": "技术部",
"parent_department_id": "0"
},
{
"department_id": "od-1234567891",
"name": "总公司",
"parent_department_id": "0"
}
],
"page_token": "next_page_token",
"has_more": false
}
}说明:
- 递归获取指定部门的父部门信息
- 从直接父部门一直追溯到根部门
- 使用用户令牌只能获取有权限查看的父部门信息
- 返回结果按层级顺序排列,可能有权限限制的父部门不会显示
代码示例:
javascript
// 获取部门完整路径(考虑权限限制)
async function getDepartmentPath(departmentId) {
const result = await feishuUserV3Departments.getParentDepartmentsByIdAsync(
departmentId,
50, // 获取更多父部门
null,
"open_id",
"open_department_id"
);
if (result.code !== 0) {
console.error("获取部门路径失败:", result.msg);
if (result.code === 403) {
console.log("权限不足,无法查看该部门的上层组织结构");
}
return null;
}
// 获取当前部门信息
const currentDeptResult = await feishuUserV3Departments.getDepartmentInfoByIdAsync(
departmentId,
"open_id",
"open_department_id"
);
const parentDepartments = result.data.items || [];
const currentDepartment = currentDeptResult.code === 0 ? currentDeptResult.data.department : null;
// 构建完整路径
const fullPath = [...parentDepartments.reverse(), currentDepartment]
.filter(dept => dept) // 过滤空值
.map(dept => ({
id: dept.department_id,
name: dept.name,
memberCount: dept.primary_member_count || 0,
hasAccess: true // 能够获取到的都是有权限的
}));
return fullPath;
}
// 显示部门路径和权限分析
async function displayDepartmentPathWithAnalysis(departmentId) {
console.log(`正在获取部门 ${departmentId} 的完整路径...`);
const path = await getDepartmentPath(departmentId);
if (!path || path.length === 0) {
console.log("未找到部门路径信息,可能没有访问权限");
return;
}
console.log("\n=== 部门完整路径 ===");
path.forEach((dept, index) => {
const arrow = index === path.length - 1 ? "" : " → ";
const memberInfo = dept.memberCount > 0 ? ` (${dept.memberCount}人)` : "";
console.log(`${dept.name}${memberInfo}${arrow}`);
});
console.log(`\n路径分析:`);
console.log(`- 路径层级: ${path.length} 层`);
console.log(`- 权限状态: 完全可访问`);
console.log(`- 是否为根部门: ${path.length === 1 ? '是' : '否'}`);
// 分析组织深度
if (path.length >= 5) {
console.log(`- 组织深度: 深层级组织 (${path.length}层)`);
} else if (path.length >= 3) {
console.log(`- 组织深度: 中等层级 (${path.length}层)`);
} else {
console.log(`- 组织深度: 扁平化组织 (${path.length}层)`);
}
return path;
}
// 比较多个部门的组织层级
async function compareDepartmentHierarchy(departmentIds) {
console.log("=== 部门层级对比分析 ===");
const comparisonResults = [];
for (const deptId of departmentIds) {
const path = await getDepartmentPath(deptId);
if (path) {
comparisonResults.push({
id: deptId,
name: path[path.length - 1].name,
level: path.length,
totalMembers: path.reduce((sum, dept) => sum + dept.memberCount, 0)
});
}
}
// 按层级排序
comparisonResults.sort((a, b) => b.level - a.level);
console.log("\n=== 层级排名 ===");
comparisonResults.forEach((result, index) => {
console.log(`${index + 1}. ${result.name}: 第${result.level}层 (${result.totalMembers}总人数)`);
});
// 统计分析
const avgLevel = Math.round(comparisonResults.reduce((sum, r) => sum + r.level, 0) / comparisonResults.length);
const deepest = Math.max(...comparisonResults.map(r => r.level));
const shallowest = Math.min(...comparisonResults.map(r => r.level));
console.log(`\n=== 统计信息 ===`);
console.log(`平均层级: ${avgLevel}`);
console.log(`最深层级: ${deepest}`);
console.log(`最浅层级: ${shallowest}`);
console.log(`层级差异: ${deepest - shallowest}`);
}
// 使用示例
async function analyzeDepartmentHierarchyExamples() {
// 显示单个部门的完整路径
await displayDepartmentPathWithAnalysis("tech_frontend_dept_001");
// 比较多个部门的层级
await compareDepartmentHierarchy([
"tech_frontend_dept_001",
"product_design_dept_001",
"sales_beijing_dept_001",
"hr_recruit_dept_001"
]);
}
analyzeDepartmentHierarchyExamples();