104 lines
2.9 KiB
JavaScript
104 lines
2.9 KiB
JavaScript
|
|
const dayjs = require('dayjs');
|
|||
|
|
|
|||
|
|
exports.generateRandomString = (length) => {
|
|||
|
|
const characters = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|||
|
|
let result = "";
|
|||
|
|
const charactersLength = characters.length;
|
|||
|
|
|
|||
|
|
for (let i = 0; i < length; i++) {
|
|||
|
|
const randomIndex = Math.floor(Math.random() * charactersLength);
|
|||
|
|
result += characters[randomIndex];
|
|||
|
|
}
|
|||
|
|
return `${result}${Date.now()}`;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 生成唯一字符串
|
|||
|
|
* @param {*} prefix 唯一字符串前缀
|
|||
|
|
* @param {*} len 补充字符串长度
|
|||
|
|
* @description 总长度 = prefix.length + 固定15 (当前时间的长度 YYMMDDHHmmssSSS格式) + 补充字符串的长度
|
|||
|
|
*/
|
|||
|
|
exports.generateUniqueStr = (prefix = '', len = 6) => {
|
|||
|
|
const dateStamp = dayjs().format('YYMMDDHHmmssSSS');
|
|||
|
|
const groups = Math.ceil(len / 4); // 4个字符串一组
|
|||
|
|
const suffix = new Array(groups).fill(1).map((_, idx) => {
|
|||
|
|
const exponent = Math.min(4, len - idx * 4);
|
|||
|
|
const str = Math.floor(Math.random() * (10 ** exponent)).toString().padStart(exponent, '0');
|
|||
|
|
return str;
|
|||
|
|
}).join('');
|
|||
|
|
return `${prefix}${dateStamp}${suffix}`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
exports.getAttachments = (fileList, sopTaskId, executeUserId) => {
|
|||
|
|
if (!Array.isArray(fileList)) return [];
|
|||
|
|
return fileList.map((item) => {
|
|||
|
|
let { type, mediaId, file, URL } = item;
|
|||
|
|
let { subtitle, name, url, type: fileType } = file;
|
|||
|
|
let attachment = {};
|
|||
|
|
if (type === "image") {
|
|||
|
|
attachment = {
|
|||
|
|
msgtype: type,
|
|||
|
|
title: name,
|
|||
|
|
image: {
|
|||
|
|
media_id: mediaId,
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
} else if (type === "video") {
|
|||
|
|
attachment = {
|
|||
|
|
msgtype: type,
|
|||
|
|
title: name,
|
|||
|
|
video: {
|
|||
|
|
media_id: mediaId,
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
} else if (type === "link") {
|
|||
|
|
attachment = {
|
|||
|
|
msgtype: type,
|
|||
|
|
title: name,
|
|||
|
|
linkType: fileType || "",
|
|||
|
|
link: {
|
|||
|
|
title: name,
|
|||
|
|
picurl: URL,
|
|||
|
|
desc: subtitle,
|
|||
|
|
url:
|
|||
|
|
fileType === "questionnaire"
|
|||
|
|
? `${url}&id=${sopTaskId}&source=sop&userId=${executeUserId}`
|
|||
|
|
: url,
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
return attachment;
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 批量执行任务,控制最大并发数
|
|||
|
|
* @param {Array} items - 待处理的任务参数列表
|
|||
|
|
* @param {Function} taskFn - 单个任务的处理函数,需返回 Promise
|
|||
|
|
* @param {number} maxConcurrency - 最大并发数
|
|||
|
|
* @returns {Promise<Array>} - 返回所有任务的结果
|
|||
|
|
*/
|
|||
|
|
exports.executeWithConcurrency = async (items, taskFn, maxConcurrency) => {
|
|||
|
|
let index = 0;
|
|||
|
|
const results = [];
|
|||
|
|
|
|||
|
|
while (index < items.length) {
|
|||
|
|
// 获取当前批次
|
|||
|
|
const batch = items.slice(index, index + maxConcurrency);
|
|||
|
|
|
|||
|
|
// 映射当前批次的任务并执行
|
|||
|
|
const promises = batch.map((item) => taskFn(item));
|
|||
|
|
|
|||
|
|
// 等待当前批次的任务完成
|
|||
|
|
const batchResults = await Promise.all(promises);
|
|||
|
|
|
|||
|
|
// 收集结果
|
|||
|
|
results.push(...batchResults);
|
|||
|
|
|
|||
|
|
// 更新索引
|
|||
|
|
index += maxConcurrency;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return results;
|
|||
|
|
};
|