Skip to content

接口名称

职务管理API(用户令牌)- IFeishuUserV3JobTitle

功能描述

职务是用户属性之一,通过职务API仅支持查询职务信息。当前接口使用用户令牌访问,适用于用户应用场景。职务API主要用于获取企业中定义的各种职务信息,包括职务ID、名称、多语言名称以及启用状态等,为用户提供职务信息查询和展示功能。

参考文档

https://open.feishu.cn/document/contact-v3/job_title/job-title-resources-introduction

函数列表

函数名称功能描述认证方式HTTP 方法
GetJobTitlesListAsync获取职务列表用户令牌GET
GetJobTitleByIdAsync获取指定职务信息用户令牌GET

函数详细内容

函数名称:获取职务列表

函数签名

csharp
Task<FeishuApiPageListResult<JobTitle>?> GetJobTitlesListAsync(
    [Query("page_size")] int? page_size = 10,
    [Query("page_token")] string? page_token = null,
    CancellationToken cancellationToken = default);

认证:用户令牌

参数

参数名类型必填说明
page_sizeint?⚪ 可选分页大小,默认10,最大50
page_tokenstring⚪ 可选分页标记,首次请求不填

响应

json
{
  "code": 0,
  "msg": "success",
  "data": {
    "items": [
      {
        "job_title_id": "jt_1234567890",
        "name": "软件工程师",
        "status": true,
        "i18n_name": [
          {
            "locale": "zh_cn",
            "text": "软件工程师"
          },
          {
            "locale": "en_us",
            "text": "Software Engineer"
          }
        ]
      },
      {
        "job_title_id": "jt_1234567891",
        "name": "产品经理",
        "status": true,
        "i18n_name": [
          {
            "locale": "zh_cn",
            "text": "产品经理"
          }
        ]
      }
    ],
    "page_token": "next_page_token",
    "has_more": true
  }
}

说明

  • 获取当前租户下的职务信息
  • 使用用户令牌只能获取有权限查看的职务信息
  • 支持分页查询,适合处理大量职务数据
  • 返回职务的基本信息,包括ID、名称、多语言名称和启用状态

代码示例

javascript
// 获取用户可访问的职务信息
async function getUserAccessibleJobTitles() {
  let hasMore = true;
  let pageToken = null;
  const allJobTitles = [];
  let pageCount = 0;

  while (hasMore) {
    pageCount++;
    console.log(`正在获取第 ${pageCount} 页职务数据...`);
    
    const result = await feishuUserV3JobTitle.getJobTitlesListAsync(
      20, // 每页获取适量数据
      pageToken
    );

    if (result.code === 0) {
      const jobTitles = result.data.items;
      allJobTitles.push(...jobTitles);
      hasMore = result.data.has_more;
      pageToken = result.data.page_token;
      
      console.log(`第 ${pageCount} 页获取到 ${jobTitles.length} 个职务`);
    } else {
      console.error(`第 ${pageCount} 页获取失败:`, result.msg);
      
      if (result.code === 403) {
        console.log("权限不足,无法访问职务信息");
      }
      break;
    }
  }

  return allJobTitles;
}

// 显示职务信息给用户
async function displayJobTitlesToUser() {
  console.log("正在获取职务列表...");
  
  const jobTitles = await getUserAccessibleJobTitles();
  
  if (jobTitles.length === 0) {
    console.log("未找到可访问的职务信息");
    return;
  }

  console.log(`\n=== 可访问的职务列表 ===`);
  console.log(`总职务数: ${jobTitles.length}`);
  
  // 按状态分类显示
  const activeJobTitles = jobTitles.filter(jt => jt.status);
  const inactiveJobTitles = jobTitles.filter(jt => !jt.status);
  
  console.log(`启用职务: ${activeJobTitles.length}`);
  console.log(`禁用职务: ${inactiveJobTitles.length}`);
  
  // 按字母排序显示
  const sortedJobTitles = [...jobTitles].sort((a, b) => a.name.localeCompare(b.name));
  
  console.log(`\n=== 职务详情 ===`);
  sortedJobTitles.forEach((jobTitle, index) => {
    const status = jobTitle.status ? '✓ 可用' : '✗ 不可用';
    const i18nInfo = jobTitle.i18n_name && jobTitle.i18n_name.length > 0 
      ? ` (${jobTitle.i18n_name.length}语言)` 
      : ' (仅中文)';
    
    console.log(`${index + 1}. ${jobTitle.name}${i18nInfo} [${status}]`);
    
    // 显示主要语言的翻译
    if (jobTitle.i18n_name && jobTitle.i18n_name.length > 0) {
      const englishName = jobTitle.i18n_name.find(item => item.locale === 'en_us');
      if (englishName) {
        console.log(`   英文: ${englishName.text}`);
      }
    }
  });
  
  return sortedJobTitles;
}

// 搜索用户可见的职务
async function searchUserJobTitles(keyword) {
  console.log(`正在搜索包含 "${keyword}" 的职务...`);
  
  const allJobTitles = await getUserAccessibleJobTitles();
  const matchedTitles = allJobTitles.filter(jt => 
    jt.name.toLowerCase().includes(keyword.toLowerCase()) ||
    (jt.i18n_name && jt.i18n_name.some(item => 
      item.text.toLowerCase().includes(keyword.toLowerCase())
    ))
  );
  
  if (matchedTitles.length === 0) {
    console.log(`未找到包含 "${keyword}" 的可访问职务`);
    return [];
  }
  
  console.log(`\n找到 ${matchedTitles.length} 个可访问的匹配职务:`);
  matchedTitles.forEach((jobTitle, index) => {
    const status = jobTitle.status ? '可用' : '不可用';
    console.log(`${index + 1}. ${jobTitle.name} [${status}]`);
    
    // 显示所有语言版本
    if (jobTitle.i18n_name && jobTitle.i18n_name.length > 0) {
      console.log(`   多语言名称:`);
      jobTitle.i18n_name.forEach(item => {
        console.log(`     ${item.locale}: ${item.text}`);
      });
    }
  });
  
  return matchedTitles;
}

// 获取当前用户的职务相关功能
async function getCurrentUserJobTitleFeatures() {
  console.log("正在分析当前用户的职务访问权限...");
  
  const jobTitles = await getUserAccessibleJobTitles();
  
  if (jobTitles.length === 0) {
    console.log("当前用户无法访问任何职务信息");
    return {
      canAccessJobTitles: false,
      totalCount: 0,
      activeCount: 0,
      features: []
    };
  }
  
  const activeCount = jobTitles.filter(jt => jt.status).length;
  const withI18nCount = jobTitles.filter(jt => jt.i18n_name && jt.i18n_name.length > 0).length;
  
  // 分析用户功能
  const features = [];
  
  if (jobTitles.length > 0) {
    features.push("职务信息查看");
  }
  
  if (jobTitles.length > 10) {
    features.push("大规模职务数据访问");
  }
  
  if (withI18nCount > 0) {
    features.push("多语言职务信息");
  }
  
  if (activeCount > 0) {
    features.push("活跃职务筛选");
  }
  
  const analysis = {
    canAccessJobTitles: true,
    totalCount: jobTitles.length,
    activeCount: activeCount,
    inactiveCount: jobTitles.length - activeCount,
    withI18nCount: withI18nCount,
    features: features
  };
  
  console.log(`\n=== 用户职务访问权限分析 ===`);
  console.log(`职务访问权限: ${analysis.canAccessJobTitles ? '有权限' : '无权限'}`);
  console.log(`可访问职务总数: ${analysis.totalCount}`);
  console.log(`可用职务数量: ${analysis.activeCount}`);
  console.log(`多语言职务数量: ${analysis.withI18nCount}`);
  console.log(`可用功能数量: ${analysis.features.length}`);
  
  console.log(`\n=== 可用功能 ===`);
  analysis.features.forEach((feature, index) => {
    console.log(`${index + 1}. ${feature}`);
  });
  
  return analysis;
}

// 职务信息用于用户选择
async function getJobTitleOptionsForSelection() {
  console.log("正在准备职务选择选项...");
  
  const jobTitles = await getUserAccessibleJobTitles();
  
  if (jobTitles.length === 0) {
    return {
      options: [],
      groups: {},
      total: 0
    };
  }
  
  // 只获取启用的职务用于选择
  const activeJobTitles = jobTitles.filter(jt => jt.status);
  
  // 按类型分组
  const groups = {
    '技术类': [],
    '管理类': [],
    '产品类': [],
    '其他': []
  };
  
  activeJobTitles.forEach(jobTitle => {
    const title = jobTitle.name;
    let group = '其他';
    
    if (['工程师', '开发', '技术', '架构', '算法', '测试', 'DevOps'].some(keyword => title.includes(keyword))) {
      group = '技术类';
    } else if (['经理', '总监', '主管', '负责人', '董事长', 'CEO', 'CTO'].some(keyword => title.includes(keyword))) {
      group = '管理类';
    } else if (['产品', '设计', '运营', '市场'].some(keyword => title.includes(keyword))) {
      group = '产品类';
    }
    
    groups[group].push({
      value: jobTitle.job_title_id,
      label: jobTitle.name,
      englishLabel: jobTitle.i18n_name ? 
        jobTitle.i18n_name.find(item => item.locale === 'en_us')?.text : null
    });
  });
  
  // 创建选项数据
  const options = [];
  Object.keys(groups).forEach(groupName => {
    if (groups[groupName].length > 0) {
      options.push({
        label: groupName,
        options: groups[groupName]
      });
    }
  });
  
  console.log(`\n=== 职务选择选项 ===`);
  console.log(`总选项数: ${activeJobTitles.length}`);
  console.log(`分组数: ${options.length}`);
  
  options.forEach(group => {
    console.log(`\n【${group.label}】(${group.options.length}个):`);
    group.options.forEach(option => {
      const englishInfo = option.englishLabel ? ` / ${option.englishLabel}` : '';
      console.log(`  ${option.label}${englishInfo} (${option.value})`);
    });
  });
  
  return {
    options: options,
    groups: groups,
    total: activeJobTitles.length
  };
}

// 使用示例
displayJobTitlesToUser();
searchUserJobTitles("工程师");
getCurrentUserJobTitleFeatures();
getJobTitleOptionsForSelection();

函数名称:获取指定职务信息

函数签名

csharp
Task<FeishuApiResult<JobTitleResult>?> GetJobTitleByIdAsync(
    [Path] string job_title_id,
    CancellationToken cancellationToken = default);

认证:用户令牌

参数

参数名类型必填说明
job_title_idstring✅ 必填职务ID

响应

json
{
  "code": 0,
  "msg": "success",
  "data": {
    "job_title": {
      "job_title_id": "jt_1234567890",
      "name": "软件工程师",
      "status": true,
      "i18n_name": [
        {
          "locale": "zh_cn",
          "text": "软件工程师"
        },
        {
          "locale": "en_us",
          "text": "Software Engineer"
        }
      ]
    }
  }
}

说明

  • 获取指定职务的详细信息
  • 使用用户令牌只能获取有权限查看的职务信息
  • 返回职务的完整属性信息
  • 包含多语言配置和状态信息

代码示例

javascript
// 获取并显示职务详情
async function getJobTitleDetailsForUser(jobTitleId) {
  console.log(`正在获取职务 ${jobTitleId} 的详细信息...`);
  
  const result = await feishuUserV3JobTitle.getJobTitleByIdAsync(jobTitleId);
  
  if (result.code === 0) {
    const jobTitle = result.data.job_title;
    
    console.log(`\n=== 职务详细信息 ===`);
    console.log(`职务ID: ${jobTitle.job_title_id}`);
    console.log(`职务名称: ${jobTitle.name}`);
    console.log(`状态: ${jobTitle.status ? '可用' : '不可用'}`);
    
    // 显示多语言信息
    if (jobTitle.i18n_name && jobTitle.i18n_name.length > 0) {
      console.log(`\n=== 多语言信息 ===`);
      console.log(`支持的语言数: ${jobTitle.i18n_name.length}`);
      
      jobTitle.i18n_name.forEach(item => {
        const currentLang = getCurrentLanguage();
        const isCurrentLang = item.locale === currentLang;
        const marker = isCurrentLang ? ' ← 当前语言' : '';
        
        console.log(`  ${item.locale}: ${item.text}${marker}`);
      });
    } else {
      console.log("该职务未配置多语言信息");
    }
    
    // 提供用户友好的描述
    console.log(`\n=== 职务说明 ===`);
    console.log(`职务类型分析: ${analyzeJobTitleType(jobTitle.name)}`);
    console.log(`访问权限: ${jobTitle.status ? '可正常使用' : '当前不可用'}`);
    
    return jobTitle;
  } else {
    console.error("获取职务信息失败:", result.msg);
    
    // 用户友好的错误处理
    switch (result.code) {
      case 404:
        console.log("职务不存在或已被删除");
        break;
      case 403:
        console.log("您没有权限查看该职务信息");
        break;
      default:
        console.log("获取失败,请稍后重试或联系管理员");
    }
    
    return null;
  }
}

// 辅助函数:分析职务类型
function analyzeJobTitleType(title) {
  if (['工程师', '开发', '技术', '架构', '算法', '测试', 'DevOps'].some(keyword => title.includes(keyword))) {
    return '技术开发类职务';
  } else if (['经理', '总监', '主管', '负责人', '董事长', 'CEO', 'CTO'].some(keyword => title.includes(keyword))) {
    return '管理类职务';
  } else if (['产品', '设计', '运营', '市场'].some(keyword => title.includes(keyword))) {
    return '产品运营类职务';
  } else if (['销售', '商务', '客户', 'BD'].some(keyword => title.includes(keyword))) {
    return '销售商务类职务';
  } else if (['人事', '财务', '行政', '法务', 'HR', 'Finance'].some(keyword => title.includes(keyword))) {
    return '职能支持类职务';
  } else {
    return '其他类型职务';
  }
}

// 辅助函数:获取当前语言环境
function getCurrentLanguage() {
  // 这里应该是实际的语言检测逻辑
  // 示例返回中文
  return 'zh_cn';
}

// 获取本地化的职务名称
async function getLocalizedJobTitle(jobTitleId, userLanguage = 'zh_cn') {
  console.log(`正在获取职务 ${jobTitleId} 的 ${userLanguage} 语言版本...`);
  
  const jobTitle = await getJobTitleDetailsForUser(jobTitleId);
  
  if (!jobTitle) {
    return null;
  }
  
  // 查找用户语言的翻译
  if (jobTitle.i18n_name && jobTitle.i18n_name.length > 0) {
    const localizedTitle = jobTitle.i18n_name.find(item => item.locale === userLanguage);
    
    if (localizedTitle) {
      console.log(`找到 ${userLanguage} 语言版本: ${localizedTitle.text}`);
      return {
        originalName: jobTitle.name,
        localizedText: localizedTitle.text,
        language: userLanguage,
        isTranslated: true
      };
    }
  }
  
  // 如果没有找到翻译,返回原名称
  console.log(`未找到 ${userLanguage} 语言版本,使用原始名称`);
  return {
    originalName: jobTitle.name,
    localizedText: jobTitle.name,
    language: 'original',
    isTranslated: false
  };
}

// 批量获取职务的本地化信息
async function getBatchLocalizedJobTitles(jobTitleIds, userLanguage = 'zh_cn') {
  console.log(`正在批量获取 ${jobTitleIds.length} 个职务的 ${userLanguage} 语言版本...`);
  
  const results = [];
  
  for (const jobTitleId of jobTitleIds) {
    const localizedInfo = await getLocalizedJobTitle(jobTitleId, userLanguage);
    
    if (localizedInfo) {
      results.push({
        jobTitleId: jobTitleId,
        ...localizedInfo
      });
    }
    
    // 添加延迟避免请求过于频繁
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  
  console.log(`\n=== 批量本地化结果 ===`);
  console.log(`成功处理: ${results.length} 个职务`);
  
  const translatedCount = results.filter(r => r.isTranslated).length;
  console.log(`已翻译: ${translatedCount} 个职务`);
  console.log(`使用原名称: ${results.length - translatedCount} 个职务`);
  
  // 显示结果
  results.forEach((result, index) => {
    const translationStatus = result.isTranslated ? '✓ 已翻译' : '○ 原名称';
    console.log(`${index + 1}. ${result.localizedText} [${translationStatus}]`);
    if (result.isTranslated) {
      console.log(`   原始名称: ${result.originalName}`);
      console.log(`   语言: ${result.language}`);
    }
  });
  
  return results;
}

// 验证职务访问权限
async function checkJobTitleAccess(jobTitleId) {
  console.log(`正在检查对职务 ${jobTitleId} 的访问权限...`);
  
  const result = await feishuUserV3JobTitle.getJobTitleByIdAsync(jobTitleId);
  
  if (result.code === 0) {
    const jobTitle = result.data.job_title;
    
    console.log(`✓ 有访问权限`);
    console.log(`职务名称: ${jobTitle.name}`);
    console.log(`职务状态: ${jobTitle.status ? '可用' : '不可用'}`);
    
    return {
      hasAccess: true,
      jobTitle: jobTitle,
      canUse: jobTitle.status
    };
  } else {
    console.log(`✗ 无访问权限`);
    
    let reason = '未知错误';
    if (result.code === 404) {
      reason = '职务不存在';
    } else if (result.code === 403) {
      reason = '权限不足';
    }
    
    console.log(`原因: ${reason}`);
    
    return {
      hasAccess: false,
      reason: reason,
      errorCode: result.code
    };
  }
}

// 使用示例
getJobTitleDetailsForUser("jt_1234567890");
getLocalizedJobTitle("jt_1234567890", "en_us");
getBatchLocalizedJobTitles(["jt_1234567890", "jt_1234567891"], "en_us");
checkJobTitleAccess("jt_1234567890");