@blueking/bk-user-display-name
Version:
多租户环境用于显示用户名称的组件
207 lines (206 loc) • 7.13 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.USER_ID_FIELD = exports.CUSTOM_ELEMENT_NAME = void 0;
exports.CUSTOM_ELEMENT_NAME = 'bk-user-display-name';
exports.USER_ID_FIELD = 'user-id';
/**
* 蓝鲸用户显示名称自定义元素类
* 用于在页面中显示用户的友好显示名称,支持缓存和批量查询
* @class BkUserDisplayName
* @extends HTMLElement
*/
class BkUserDisplayName extends HTMLElement {
constructor() {
super();
}
/**
* 配置类的静态参数
* @static
* @param {ConfigOptions} config - 配置选项
* @returns {void}
*/
static configure(config) {
if (config.apiBaseUrl) {
this.apiBaseUrl = config.apiBaseUrl;
}
if (config.tenantId) {
this.tenantId = config.tenantId;
}
if (typeof config.cacheDuration === 'number') {
this.cacheDuration = config.cacheDuration;
}
if (config.emptyText !== undefined) {
this.emptyText = config.emptyText;
}
}
/**
* 通用请求配置
* @private
* @returns {RequestInit} 通用请求配置
*/
createFetchConfig() {
return {
credentials: 'include',
headers: {
'X-Bk-Tenant-Id': BkUserDisplayName.tenantId,
},
};
}
/**
* 获取单个用户信息
* 支持请求去重,避免同时发起多个相同的请求
* @async
* @param {string} id - 用户ID
* @returns {Promise<UserResponse>} 用户信息
*/
async fetchUser(id) {
const pendingRequest = BkUserDisplayName.pendingRequests.get(id);
if (pendingRequest) {
return pendingRequest;
}
const promise = fetch(`${BkUserDisplayName.apiBaseUrl}/api/v3/open-web/tenant/users/${id}/display_info/`, this.createFetchConfig())
.then(response => response.json())
.finally(() => {
BkUserDisplayName.pendingRequests.delete(id);
});
BkUserDisplayName.pendingRequests.set(id, promise);
return promise;
}
/**
* 批量获取多个用户信息
* @async
* @param {string[]} ids - 用户ID数组
* @returns {Promise<UsersResponse>} 用户信息列表
*/
async fetchUsers(ids) {
return fetch(`${BkUserDisplayName.apiBaseUrl}/api/v3/open-web/tenant/users/-/display_info/?bk_usernames=${ids.join(',')}`, this.createFetchConfig()).then(response => response.json());
}
/**
* 检查缓存是否仍然有效
* @private
* @param {UserCacheItem} cached - 缓存项
* @returns {boolean} 缓存是否有效
*/
isCacheValid(cached) {
return Date.now() - cached.timestamp < BkUserDisplayName.cacheDuration;
}
/**
* 解析用户ID字符串为ID数组
* 支持逗号、中文逗号、分号分隔
* @private
* @param {string} userIdString - 用户ID字符串
* @returns {string[]} 解析后的用户ID数组
*/
parseUserIds(userIdString) {
return decodeURIComponent(userIdString).split(/[,,;]/).filter(id => id.trim()).map(id => id.trim());
}
/**
* 获取单个用户的显示名称
* 优先使用缓存,缓存失效时重新请求
* @private
* @async
* @param {string} id - 用户ID
* @returns {Promise<string>} 用户显示名称
*/
async getSingleUserDisplayName(id) {
var _a;
const cached = BkUserDisplayName.userCache.get(id);
let userResponse;
if (cached && this.isCacheValid(cached)) {
userResponse = cached.data;
}
else {
userResponse = await this.fetchUser(id);
BkUserDisplayName.userCache.set(id, {
data: userResponse,
timestamp: Date.now(),
});
}
return ((_a = userResponse.data) === null || _a === void 0 ? void 0 : _a.display_name) || id;
}
/**
* 获取多个用户的显示名称
* @private
* @async
* @param {string[]} ids - 用户ID数组
* @returns {Promise<string>} 逗号分隔的用户显示名称字符串
*/
async getMultipleUsersDisplayName(ids) {
const usersResponse = await this.fetchUsers(ids);
const userList = ids.map(id => {
var _a;
const user = (_a = usersResponse.data) === null || _a === void 0 ? void 0 : _a.find((user) => user.bk_username === id);
return (user === null || user === void 0 ? void 0 : user.display_name) || id;
});
return userList.join(', ');
}
/**
* 获取用户显示名称
* 根据用户ID的数量选择单个或批量获取方式
* @async
* @returns {Promise<string>} 用户显示名称或用户ID(获取失败时)
*/
async getDisplayName() {
var _a;
const id = (_a = this.getAttribute(exports.USER_ID_FIELD)) === null || _a === void 0 ? void 0 : _a.trim();
if (!id)
return '';
// 如果未配置,则直接展示用户配置 这里用于 当前项目回退到原来的展示方式
if (!BkUserDisplayName.apiBaseUrl || !BkUserDisplayName.tenantId)
return id;
const ids = this.parseUserIds(id);
try {
if (ids.length === 1) {
return await this.getSingleUserDisplayName(id);
}
else {
return await this.getMultipleUsersDisplayName(ids);
}
}
catch (error) {
console.error('DisplayName 获取用户数据失败:', error);
return id;
}
}
/**
* 更新元素显示内容
* @async
* @returns {Promise<void>}
*/
async updateDisplay() {
const id = this.getAttribute(exports.USER_ID_FIELD);
if (!id) {
this.textContent = BkUserDisplayName.emptyText;
return;
}
this.textContent = '...';
this.textContent = await this.getDisplayName();
}
/**
* 当user-id属性发生变化时触发显示更新
*/
attributeChangedCallback(name, oldValue, newValue) {
if (name === exports.USER_ID_FIELD && oldValue !== newValue) {
this.updateDisplay();
}
}
}
exports.default = BkUserDisplayName;
/** 用户数据缓存 */
BkUserDisplayName.userCache = new Map();
/** 缓存过期时间(毫秒),默认5分钟 */
BkUserDisplayName.cacheDuration = 5 * 60 * 1000;
/** 存储进行中的请求,避免重复请求 */
BkUserDisplayName.pendingRequests = new Map();
/** API基础URL */
BkUserDisplayName.apiBaseUrl = '';
/** 租户ID */
BkUserDisplayName.tenantId = '';
/** 当输入为空时显示的文本 */
BkUserDisplayName.emptyText = '--';
/** 定义需要监听的属性列表 */
BkUserDisplayName.observedAttributes = [exports.USER_ID_FIELD];
// 微前端框架下,有多个应用重复注册
if (!customElements.get(exports.CUSTOM_ELEMENT_NAME)) {
customElements.define(exports.CUSTOM_ELEMENT_NAME, BkUserDisplayName);
}