用户任务评论管理 - (IFeishuUserV2TaskComments)
功能描述
个人任务评论管理接口,实现评论创建、回复、更新、删除、获取详情等功能。支持用户为自己有权限的任务创建评论或回复评论,并可以获取评论的详细信息。用户可以管理自己创建的评论内容,支持分页查询和排序。该接口使用用户令牌进行认证,确保用户只能操作自己有权限的任务评论。
参考文档
https://open.feishu.cn/document/task-v2/comment/overview
函数列表
| 函数名称 | 功能描述 | 认证方式 | HTTP 方法 |
|---|---|---|---|
| CreateCommentAsync | 为一个任务创建个人评论,或者回复该任务的某个评论 | 用户令牌 | POST |
| GetCommentByIdAsync | 给定一个评论的ID,返回个人评论的详情,包括内容、创建人、创建时间和更新时间等信息 | 用户令牌 | GET |
| UpdateCommentByIdAsync | 更新一条个人评论,支持部分字段更新 | 用户令牌 | PATCH |
| DeleteCommentByIdAsync | 删除一条个人评论,删除后将无法进行任何操作,也无法恢复 | 用户令牌 | DELETE |
| GetCommentPageListAsync | 给定一个资源,返回该资源的个人评论列表,支持分页和排序 | 用户令牌 | GET |
函数详细内容
创建评论
函数签名:
csharp
Task<FeishuApiResult<CommentOpreationResult>?> CreateCommentAsync(
[Body] CreateCommentRequest createCommentRequest,
[Query("user_id_type")] string user_id_type = Consts.User_Id_Type,
CancellationToken cancellationToken = default);认证:用户令牌
参数:
- ✅ createCommentRequest (CreateCommentRequest): 创建评论请求体,包含评论内容、关联资源信息等
- ⚪ user_id_type (string): 用户ID类型,默认值为Consts.User_Id_Type
- ⚪ cancellationToken (CancellationToken): 取消操作令牌对象
响应:
json
{
"code": 0,
"data": {
"comment": {
"comment_id": "7198104824246747156",
"resource_id": "d300a75f-c56a-4be9-80d1-e47653028ceb",
"resource_type": "task",
"content": "我已完成第一阶段的开发工作,请审核。",
"created": "2024-01-01T10:00:00Z",
"updated": "2024-01-01T10:00:00Z",
"reply_to_comment_id": null,
"create_user": {
"user_id": "user_self",
"name": "张三",
"email": "zhangsan@example.com"
}
}
},
"msg": "success"
}说明:为一个任务创建评论,或者回复该任务的某个评论。若要创建一个回复评论,需要在创建时设置reply_to_comment_id字段。被回复的评论和新建的评论必须属于同一个任务。用户只能为自己有权限的任务创建评论。
代码示例:
typescript
// 创建个人新评论
const createCommentRequest = {
resource_id: "d300a75f-c56a-4be9-80d1-e47653028ceb",
resource_type: "task",
content: "个人进度更新:已完成UI设计部分,正在进行前端开发。"
};
const response = await feishuUserClient.createComment(createCommentRequest);
console.log("个人评论创建成功:", response.data.comment);
// 创建回复评论
const createReplyRequest = {
resource_id: "d300a75f-c56a-4be9-80d1-e47653028ceb",
resource_type: "task",
content: "收到,我会尽快完成剩余的测试工作。",
reply_to_comment_id: "7198104824246747156"
};
const replyResponse = await feishuUserClient.createComment(createReplyRequest);
console.log("个人评论回复成功:", replyResponse.data.comment);
// 批量创建进度更新评论
async function addProgressUpdates(taskIds: string[], progressStatus: string) {
const results = [];
for (const taskId of taskIds) {
try {
const request = {
resource_id: taskId,
resource_type: "task",
content: `个人进度更新:${progressStatus}`
};
const response = await feishuUserClient.createComment(request);
results.push({
taskId: taskId,
success: true,
commentId: response.data.comment.comment_id,
timestamp: response.data.comment.created
});
console.log(`任务 ${taskId} 进度更新成功`);
// 添加延迟避免请求过快
await new Promise(resolve => setTimeout(resolve, 100));
} catch (error) {
results.push({
taskId: taskId,
success: false,
error: error.message
});
console.log(`任务 ${taskId} 进度更新失败: ${error.message}`);
}
}
return results;
}
// 使用批量更新功能
const taskIds = ["task_1", "task_2", "task_3"];
const progressMessage = "已完成80%的开发工作,预计明日完成全部任务。";
const results = await addProgressUpdates(taskIds, progressMessage);
console.log("批量进度更新结果:");
results.forEach(result => {
if (result.success) {
console.log(`✓ 任务 ${result.taskId}: ${result.timestamp}`);
} else {
console.log(`✗ 任务 ${result.taskId}: ${result.error}`);
}
});
// 创建带时间戳的评论模板
function createTimestampedComment(content: string) {
const timestamp = new Date().toLocaleString('zh-CN');
return `[${timestamp}] ${content}`;
}
// 使用时间戳模板
const timestampedComment = {
resource_id: "d300a75f-c56a-4be9-80d1-e47653028ceb",
resource_type: "task",
content: createTimestampedComment("开始处理任务,预计2小时后完成。")
};
const timestampedResponse = await feishuUserClient.createComment(timestampedComment);
console.log("带时间戳的评论:", timestampedResponse.data.comment.content);获取评论详情
函数签名:
csharp
Task<FeishuApiResult<CommentOpreationResult>?> GetCommentByIdAsync(
[Path] string comment_id,
[Query("user_id_type")] string user_id_type = Consts.User_Id_Type,
CancellationToken cancellationToken = default);认证:用户令牌
参数:
- ✅ comment_id (string): 要获取评论详情的评论ID,示例值:"7198104824246747156"
- ⚪ user_id_type (string): 用户ID类型,默认值为Consts.User_Id_Type
- ⚪ cancellationToken (CancellationToken): 取消操作令牌对象
响应:
json
{
"code": 0,
"data": {
"comment": {
"comment_id": "7198104824246747156",
"resource_id": "d300a75f-c56a-4be9-80d1-e47653028ceb",
"resource_type": "task",
"content": "我已完成第一阶段的开发工作,请审核。",
"created": "2024-01-01T10:00:00Z",
"updated": "2024-01-01T15:30:00Z",
"reply_to_comment_id": null,
"create_user": {
"user_id": "user_self",
"name": "张三",
"email": "zhangsan@example.com"
}
}
},
"msg": "success"
}说明:给定一个评论的ID,返回个人评论的详情,包括内容,创建人,创建时间和更新时间等信息。用户只能查看自己有权限的评论详情。
代码示例:
typescript
const response = await feishuUserClient.getCommentById("7198104824246747156");
const comment = response.data.comment;
console.log("个人评论详情:");
console.log(`评论ID: ${comment.comment_id}`);
console.log(`内容: ${comment.content}`);
console.log(`创建者: ${comment.create_user.name} (${comment.create_user.email})`);
console.log(`创建时间: ${comment.created}`);
console.log(`更新时间: ${comment.updated}`);
console.log(`所属任务: ${comment.resource_id}`);
console.log(`是否为回复: ${comment.reply_to_comment_id ? '是' : '否'}`);
// 分析评论的编辑情况
const createdTime = new Date(comment.created);
const updatedTime = new Date(comment.updated);
const wasEdited = updatedTime > createdTime;
if (wasEdited) {
const editDuration = updatedTime.getTime() - createdTime.getTime();
const editMinutes = Math.floor(editDuration / (1000 * 60));
const editHours = Math.floor(editMinutes / 60);
console.log(`评论已被编辑过:`);
console.log(`- 编辑时间距离创建: ${editHours} 小时 ${editMinutes % 60} 分钟`);
console.log(`- 原创建时间: ${createdTime.toLocaleString('zh-CN')}`);
console.log(`- 最后更新: ${updatedTime.toLocaleString('zh-CN')}`);
} else {
console.log("评论未被编辑");
}
// 检查是否为自己的评论
if (comment.create_user.user_id === "user_self") {
console.log("这是您自己创建的评论,可以进行编辑或删除操作");
// 获取评论的操作选项
const now = new Date();
const commentAge = now.getTime() - createdTime.getTime();
const hoursSinceCreation = Math.floor(commentAge / (1000 * 60 * 60));
console.log("可用操作:");
console.log("- 编辑: ✓ (可编辑内容)");
console.log("- 删除: ✓ (可永久删除)");
console.log(`- 评论时长: ${hoursSinceCreation} 小时`);
if (hoursSinceCreation > 24) {
console.log("⚠ 注意: 评论已超过24小时,编辑前请确认内容的准确性");
}
} else {
console.log("这是其他用户创建的评论,您只能查看");
}
// 批量获取个人评论的详细信息
async function getPersonalCommentDetails(commentIds: string[]) {
const commentDetails = [];
for (const commentId of commentIds) {
try {
const response = await feishuUserClient.getCommentById(commentId);
const comment = response.data.comment;
const detail = {
commentId: commentId,
success: true,
content: comment.content,
author: comment.create_user.name,
createdAt: comment.created,
updatedAt: comment.updated,
isEdited: new Date(comment.updated) > new Date(comment.created),
isOwn: comment.create_user.user_id === "user_self",
isReply: comment.reply_to_comment_id !== null,
taskId: comment.resource_id
};
commentDetails.push(detail);
} catch (error) {
commentDetails.push({
commentId: commentId,
success: false,
error: error.message
});
}
}
return commentDetails;
}
// 使用批量获取功能
const commentIds = ["comment_1", "comment_2", "comment_3"];
const details = await getPersonalCommentDetails(commentIds);
console.log("个人评论详细信息:");
details.forEach(detail => {
if (detail.success) {
const status = [];
if (detail.isEdited) status.push("已编辑");
if (detail.isOwn) status.push("自己的");
if (detail.isReply) status.push("回复");
console.log(`${detail.author}: ${detail.content}`);
console.log(` 状态: ${status.join(", ") || "普通评论"}`);
console.log(` 时间: ${detail.createdAt}`);
console.log(` 任务: ${detail.taskId}`);
console.log("");
} else {
console.log(`评论 ${detail.commentId} 获取失败: ${detail.error}`);
}
});更新评论
函数签名:
csharp
Task<FeishuApiResult<CommentOpreationResult>?> UpdateCommentByIdAsync(
[Path] string comment_id,
[Body] UpdateCommentRequest updateCommentRequest,
[Query("user_id_type")] string user_id_type = Consts.User_Id_Type,
CancellationToken cancellationToken = default);认证:用户令牌
参数:
- ✅ comment_id (string): 要更新评论详情的评论ID,示例值:"7198104824246747156"
- ✅ updateCommentRequest (UpdateCommentRequest): 更新评论请求体
- ⚪ user_id_type (string): 用户ID类型,默认值为Consts.User_Id_Type
- ⚪ cancellationToken (CancellationToken): 取消操作令牌对象
响应:
json
{
"code": 0,
"data": {
"comment": {
"comment_id": "7198104824246747156",
"resource_id": "d300a75f-c56a-4be9-80d1-e47653028ceb",
"resource_type": "task",
"content": "更新后的个人评论内容",
"created": "2024-01-01T10:00:00Z",
"updated": "2024-01-01T16:45:00Z",
"reply_to_comment_id": null,
"create_user": {
"user_id": "user_self",
"name": "张三",
"email": "zhangsan@example.com"
}
}
},
"msg": "success"
}说明:更新一条个人评论。更新时,将update_fields字段中填写所有要修改的评论的字段名,同时在comment字段中填写要修改的字段的新值即可。用户只能更新自己创建的评论。
代码示例:
typescript
const updateCommentRequest = {
update_fields: ["content"],
comment: {
content: "更新进度:已完成90%的开发工作,正在进行最后测试,预计明日中午前完成。"
}
};
const response = await feishuUserClient.updateCommentById(
"7198104824246747156",
updateCommentRequest
);
const updatedComment = response.data.comment;
console.log("个人评论更新成功:", updatedComment.content);
console.log("更新时间:", updatedComment.updated);
// 安全更新个人评论(先检查权限)
async function safeUpdatePersonalComment(commentId: string, newContent: string) {
try {
// 1. 获取评论详情检查权限
const detailResponse = await feishuUserClient.getCommentById(commentId);
const comment = detailResponse.data.comment;
// 2. 检查是否为自己的评论
if (comment.create_user.user_id !== "user_self") {
throw new Error("无权编辑其他用户的评论");
}
// 3. 显示原内容供确认
console.log("准备更新个人评论:");
console.log(`原内容: ${comment.content}`);
console.log(`新内容: ${newContent}`);
console.log(`创建时间: ${comment.created}`);
// 4. 确认更新
const confirmed = confirm("确定要更新这条评论吗?");
if (!confirmed) {
console.log("用户取消了更新操作");
return null;
}
// 5. 执行更新
const updateRequest = {
update_fields: ["content"],
comment: { content: newContent }
};
const updateResponse = await feishuUserClient.updateCommentById(commentId, updateRequest);
console.log("个人评论更新成功:");
console.log(`评论ID: ${updateResponse.data.comment.comment_id}`);
console.log(`更新时间: ${updateResponse.data.comment.updated}`);
return updateResponse.data.comment;
} catch (error) {
console.error("更新个人评论失败:", error.message);
// 检查具体错误类型
if (error.message.includes("403") || error.message.includes("permission")) {
console.log("错误原因: 没有编辑此评论的权限");
} else if (error.message.includes("404")) {
console.log("错误原因: 评论不存在或已被删除");
}
return null;
}
}
// 使用安全更新功能
const safeUpdateResult = await safeUpdatePersonalComment(
"7198104824246747156",
"最新进展:已完成全部开发工作,正在准备测试环境,请安排测试。"
);
// 批量更新个人进度评论
async function batchUpdateProgressComments(commentIds: string[], progressTemplate: (comment: any) => string) {
const results = [];
for (const commentId of commentIds) {
try {
// 获取原评论
const detailResponse = await feishuUserClient.getCommentById(commentId);
const comment = detailResponse.data.comment;
// 检查权限
if (comment.create_user.user_id !== "user_self") {
results.push({
commentId: commentId,
success: false,
error: "无权编辑其他用户的评论"
});
continue;
}
// 生成新内容
const newContent = progressTemplate(comment);
// 更新评论
const updateRequest = {
update_fields: ["content"],
comment: { content: newContent }
};
await feishuUserClient.updateCommentById(commentId, updateRequest);
results.push({
commentId: commentId,
success: true,
oldContent: comment.content,
newContent: newContent,
updatedAt: new Date().toISOString()
});
console.log(`评论 ${commentId} 更新成功`);
// 添加延迟
await new Promise(resolve => setTimeout(resolve, 200));
} catch (error) {
results.push({
commentId: commentId,
success: false,
error: error.message
});
console.log(`评论 ${commentId} 更新失败: ${error.message}`);
}
}
return results;
}
// 使用批量更新功能
const commentIds = ["comment_1", "comment_2"];
const batchResults = await batchUpdateProgressComments(commentIds, (comment) => {
return `【更新 ${new Date().toLocaleDateString()}】原内容已更新,请查看最新状态。`;
});
console.log("批量更新结果:");
batchResults.forEach(result => {
if (result.success) {
console.log(`✓ 评论 ${result.commentId}:`);
console.log(` 原: ${result.oldContent.substring(0, 50)}...`);
console.log(` 新: ${result.newContent.substring(0, 50)}...`);
} else {
console.log(`✗ 评论 ${result.commentId}: ${result.error}`);
}
});删除评论
函数签名:
csharp
Task<FeishuNullDataApiResult?> DeleteCommentByIdAsync(
[Path] string comment_id,
[Query("user_id_type")] string user_id_type = Consts.User_Id_Type,
CancellationToken cancellationToken = default);认证:用户令牌
参数:
- ✅ comment_id (string): 要删除评论详情的评论ID,示例值:"7198104824246747156"
- ⚪ user_id_type (string): 用户ID类型,默认值为Consts.User_Id_Type
- ⚪ cancellationToken (CancellationToken): 取消操作令牌对象
响应:
json
{
"code": 0,
"data": null,
"msg": "success"
}说明:删除一条个人评论。评论被删除后,将无法进行任何操作,也无法恢复,请谨慎操作。用户只能删除自己创建的评论。
代码示例:
typescript
// 安全删除个人评论:先检查权限,确认后删除
async function safeDeletePersonalComment(commentId: string) {
try {
// 1. 获取评论详情
const detailResponse = await feishuUserClient.getCommentById(commentId);
const comment = detailResponse.data.comment;
// 2. 检查是否为自己的评论
if (comment.create_user.user_id !== "user_self") {
throw new Error("无权删除其他用户的评论");
}
// 3. 显示评论信息供确认
console.log("准备删除个人评论:");
console.log(`评论ID: ${comment.comment_id}`);
console.log(`内容: ${comment.content}`);
console.log(`创建时间: ${comment.created}`);
console.log(`所属任务: ${comment.resource_id}`);
// 检查评论是否被回复
if (comment.reply_to_comment_id) {
console.log(`这是回复评论,原评论ID: ${comment.reply_to_comment_id}`);
}
// 4. 确认删除
const confirmed = confirm(`确定要删除这条个人评论吗?\n内容: ${comment.content.substring(0, 50)}...\n\n此操作不可恢复!`);
if (confirmed) {
// 5. 执行删除操作
const deleteResponse = await feishuUserClient.deleteCommentById(commentId);
if (deleteResponse.code === 0) {
console.log(`个人评论删除成功: ${comment.comment_id}`);
// 记录删除日志
const deletionLog = {
commentId: commentId,
content: comment.content,
createdAt: comment.created,
deletedAt: new Date().toISOString(),
taskId: comment.resource_id,
deletionReason: "用户主动删除"
};
console.log("删除日志:", deletionLog);
return true;
} else {
console.log(`删除失败: ${deleteResponse.msg}`);
return false;
}
} else {
console.log("用户取消了删除操作");
return false;
}
} catch (error) {
console.log(`删除个人评论失败: ${error.message}`);
// 检查错误类型
if (error.message.includes("403") || error.message.includes("permission")) {
console.log("可能的原因: 没有删除此评论的权限");
} else if (error.message.includes("404")) {
console.log("可能的原因: 评论不存在或已被删除");
}
return false;
}
}
// 使用安全删除功能
const deleteResult = await safeDeletePersonalComment("7198104824246747156");
// 批量清理个人旧评论
async function cleanupOldPersonalComments(taskId: string, daysThreshold: number = 30) {
try {
// 1. 获取任务的所有评论
const commentsResponse = await feishuUserClient.getCommentPageList({
resource_id: taskId,
page_size: 100
});
// 2. 筛选自己的旧评论
const thresholdDate = new Date();
thresholdDate.setDate(thresholdDate.getDate() - daysThreshold);
const oldPersonalComments = commentsResponse.data.items.filter(comment => {
const isOwn = comment.create_user.user_id === "user_self";
const isOld = new Date(comment.created) < thresholdDate;
return isOwn && isOld;
});
if (oldPersonalComments.length === 0) {
console.log(`没有找到超过 ${daysThreshold} 天的个人评论`);
return { total: 0, deleted: 0 };
}
console.log(`找到 ${oldPersonalComments.length} 条超过 ${daysThreshold} 天的个人评论:`);
oldPersonalComments.forEach(comment => {
console.log(`- ${comment.content.substring(0, 40)}... (${comment.created})`);
});
// 3. 确认批量删除
const confirmed = confirm(`确定要删除这 ${oldPersonalComments.length} 条旧评论吗?\n\n此操作不可恢复!`);
if (!confirmed) {
console.log("用户取消了批量删除操作");
return { total: oldPersonalComments.length, deleted: 0 };
}
// 4. 执行批量删除
let deletedCount = 0;
for (const comment of oldPersonalComments) {
try {
await feishuUserClient.deleteCommentById(comment.comment_id);
console.log(`已删除: ${comment.comment_id}`);
deletedCount++;
// 添加延迟避免请求过快
await new Promise(resolve => setTimeout(resolve, 100));
} catch (error) {
console.log(`删除失败: ${comment.comment_id}, 错误: ${error.message}`);
}
}
console.log(`批量删除完成: 成功删除 ${deletedCount}/${oldPersonalComments.length} 条个人评论`);
return { total: oldPersonalComments.length, deleted: deletedCount };
} catch (error) {
console.error("清理个人旧评论失败:", error);
return { total: 0, deleted: 0 };
}
}
// 使用清理功能
const cleanupResult = await cleanupOldPersonalComments(
"d300a75f-c56a-4be9-80d1-e47653028ceb",
30
);
console.log(`清理结果: 发现 ${cleanupResult.total} 条,删除 ${cleanupResult.deleted} 条`);获取评论列表
函数签名:
csharp
Task<FeishuApiPageListResult<TaskCommentInfo>?> GetCommentPageListAsync(
[Query("resource_id")] string? resource_id = null,
[Query("resource_type")] string? resource_type = "task",
[Query("direction")] string? direction = "asc",
[Query("page_size")] int page_size = 10,
[Query("page_token")] string? page_token = null,
[Query("user_id_type")] string user_id_type = Consts.User_Id_Type,
CancellationToken cancellationToken = default);认证:用户令牌
参数:
- ⚪ resource_id (string): 要获取评论的资源ID,例如个人任务全局唯一ID,示例值:"d300a75f-c56a-4be9-80d1-e47653028ceb"
- ⚪ resource_type (string): 要获取评论列表的资源类型,目前只支持"task",默认为"task",示例值:"task"
- ⚪ direction (string): 返回数据的排序方式,"asc"表示从最老到最新顺序返回;"desc"表示从最新到最老顺序返回。默认为"asc"
- ⚪ page_size (int): 分页大小,默认值:10
- ⚪ page_token (string): 分页标记,第一次请求不填
- ⚪ user_id_type (string): 用户ID类型,默认值为Consts.User_Id_Type
- ⚪ cancellationToken (CancellationToken): 取消操作令牌对象
响应:
json
{
"code": 0,
"data": {
"items": [
{
"comment_id": "7198104824246747156",
"resource_id": "d300a75f-c56a-4be9-80d1-e47653028ceb",
"resource_type": "task",
"content": "个人进度更新:已完成UI设计部分。",
"created": "2024-01-01T10:00:00Z",
"updated": "2024-01-01T10:00:00Z",
"reply_to_comment_id": null,
"create_user": {
"user_id": "user_self",
"name": "张三",
"email": "zhangsan@example.com"
}
}
],
"page_token": "next_page_token",
"has_more": true
},
"msg": "success"
}说明:给定一个资源,返回该资源的个人评论列表。支持分页。评论可以按照创建时间的正序(asc, 从最老到最新),或者逆序(desc,从最老到最新),返回数据。用户只能查看自己有权限的评论列表。
代码示例:
typescript
// 获取个人任务的所有评论(按时间正序)
const response = await feishuUserClient.getCommentPageList({
resource_id: "d300a75f-c56a-4be9-80d1-e47653028ceb",
resource_type: "task",
direction: "asc",
page_size: 20
});
const comments = response.data.items;
console.log(`获取到 ${comments.length} 条评论:`);
comments.forEach((comment, index) => {
const isOwn = comment.create_user.user_id === "user_self";
const isEdited = new Date(comment.updated) > new Date(comment.created);
const isReply = comment.reply_to_comment_id !== null;
const badges = [];
if (isOwn) badges.push("自己");
if (isEdited) badges.push("已编辑");
if (isReply) badges.push("回复");
const badgeText = badges.length > 0 ? ` [${badges.join(", ")}]` : "";
console.log(`${index + 1}. ${comment.create_user.name}${badgeText}: ${comment.content}`);
console.log(` 时间: ${comment.created}`);
if (isReply) {
console.log(` 回复: ${comment.reply_to_comment_id}`);
}
console.log("");
});
// 分页获取所有评论
async function getAllPersonalComments(taskId: string, direction: string = "asc") {
let pageToken: string | undefined = undefined;
let allComments = [];
let pageCount = 0;
do {
pageCount++;
console.log(`正在获取第 ${pageCount} 页评论...`);
const pageResponse = await feishuUserClient.getCommentPageList({
resource_id: taskId,
resource_type: "task",
direction: direction,
page_size: 50,
page_token: pageToken
});
allComments.push(...pageResponse.data.items);
pageToken = pageResponse.data.page_token;
console.log(`第 ${pageCount} 页获取到 ${pageResponse.data.items.length} 条评论,总计 ${allComments.length} 条`);
} while (pageToken);
return allComments;
}
// 个人评论统计分析
async function analyzePersonalComments(taskId: string) {
const allComments = await getAllPersonalComments(taskId);
if (allComments.length === 0) {
console.log("该任务暂无评论");
return null;
}
// 筛选自己的评论
const personalComments = allComments.filter(comment => comment.create_user.user_id === "user_self");
const otherComments = allComments.filter(comment => comment.create_user.user_id !== "user_self");
// 基础统计
const analysis = {
totalComments: allComments.length,
personalComments: personalComments.length,
otherComments: otherComments.length,
dateRange: {
earliest: new Date(Math.min(...allComments.map(c => new Date(c.created).getTime()))),
latest: new Date(Math.max(...allComments.map(c => new Date(c.created).getTime())))
},
replies: allComments.filter(c => c.reply_to_comment_id !== null).length,
personalReplies: personalComments.filter(c => c.reply_to_comment_id !== null).length,
editedPersonalComments: personalComments.filter(c => new Date(c.updated) > new Date(c.created)).length
};
// 按日期统计个人评论
const personalDateStats = personalComments.reduce((acc, comment) => {
const date = new Date(comment.created).toLocaleDateString();
acc[date] = (acc[date] || 0) + 1;
return acc;
}, {});
// 最近活动
const recentThreshold = new Date();
recentThreshold.setHours(recentThreshold.getHours() - 24);
const recentPersonalComments = personalComments.filter(
comment => new Date(comment.created) > recentThreshold
);
console.log("个人评论分析结果:");
console.log(`总评论数: ${analysis.totalComments}`);
console.log(`个人评论数: ${analysis.personalComments} (${((analysis.personalComments / analysis.totalComments) * 100).toFixed(1)}%)`);
console.log(`他人评论数: ${analysis.otherComments}`);
console.log(`时间范围: ${analysis.dateRange.earliest.toLocaleDateString()} 至 ${analysis.dateRange.latest.toLocaleDateString()}`);
console.log(`回复评论数: ${analysis.replies} (个人回复: ${analysis.personalReplies})`);
console.log(`编辑过的个人评论数: ${analysis.editedPersonalComments}`);
console.log(`最近24小时个人评论: ${recentPersonalComments.length}`);
console.log("\n个人评论按日期统计:");
Object.entries(personalDateStats).forEach(([date, count]) => {
console.log(`${date}: ${count} 条个人评论`);
});
return {
analysis: analysis,
personalComments: personalComments,
personalDateStats: personalDateStats,
recentActivity: recentPersonalComments
};
}
// 使用分析功能
const personalCommentAnalysis = await analyzePersonalComments("d300a75f-c56a-4be9-80d1-e47653028ceb");
// 查找可编辑的个人评论
if (personalCommentAnalysis) {
const editableComments = personalCommentAnalysis.personalComments.filter(comment => {
// 可以编辑自己的评论
return comment.create_user.user_id === "user_self";
});
console.log(`\n可编辑的个人评论: ${editableComments.length} 条`);
editableComments.forEach(comment => {
const timeAgo = getTimeAgo(new Date(comment.created));
console.log(`- ${comment.comment_id}: ${comment.content.substring(0, 30)}... (${timeAgo})`);
});
}
// 辅助函数:计算时间差
function getTimeAgo(date: Date): string {
const now = new Date();
const diffInMinutes = Math.floor((now.getTime() - date.getTime()) / (1000 * 60));
if (diffInMinutes < 60) {
return `${diffInMinutes} 分钟前`;
} else if (diffInMinutes < 1440) {
return `${Math.floor(diffInMinutes / 60)} 小时前`;
} else {
return `${Math.floor(diffInMinutes / 1440)} 天前`;
}
}
// 获取特定用户的评论(包括自己和他人的)
function getCommentsByUser(comments: any[], userName: string) {
return comments.filter(comment =>
comment.create_user.name.toLowerCase().includes(userName.toLowerCase())
);
}
// 查找包含关键词的评论
function findCommentsByKeyword(comments: any[], keyword: string) {
return comments.filter(comment =>
comment.content.toLowerCase().includes(keyword.toLowerCase())
);
}
// 使用查找功能
if (personalCommentAnalysis) {
// 查找自己的评论
const myComments = getCommentsByUser(personalCommentAnalysis.personalComments, "张三");
console.log(`\n自己的评论: ${myComments.length} 条`);
// 查找包含"进度"的评论
const progressComments = findCommentsByKeyword(personalCommentAnalysis.personalComments, "进度");
console.log(`包含"进度"的个人评论: ${progressComments.length} 条`);
progressComments.forEach(comment => {
console.log(`- ${comment.content} (${comment.created})`);
});
}个人评论管理最佳实践
个人评论管理器类
typescript
class PersonalCommentManager {
private userClient: any;
constructor(userClient: any) {
this.userClient = userClient;
}
// 创建带状态标签的评论
async createStatusComment(taskId: string, status: string, details?: string) {
const statusLabels = {
'开始': '🚀',
'进行中': '⏳',
'完成': '✅',
'暂停': '⏸️',
'问题': '❌',
'更新': '🔄'
};
const emoji = statusLabels[status] || '📝';
const timestamp = new Date().toLocaleString('zh-CN');
const content = details
? `${emoji} 【${status}】${details}\n⏰ ${timestamp}`
: `${emoji} 【${status}】\n⏰ ${timestamp}`;
const request = {
resource_id: taskId,
resource_type: "task",
content: content
};
const response = await this.userClient.createComment(request);
console.log(`状态评论创建成功: ${status}`);
return response.data.comment;
}
// 获取个人评论摘要
async getPersonalCommentSummary(taskId: string) {
const allComments = await this.getAllComments(taskId);
const personalComments = allComments.filter(c => c.create_user.user_id === "user_self");
const summary = {
totalPersonalComments: personalComments.length,
recentActivity: personalComments.filter(c => {
const hoursAgo = (Date.now() - new Date(c.created).getTime()) / (1000 * 60 * 60);
return hoursAgo <= 24;
}).length,
editedCount: personalComments.filter(c =>
new Date(c.updated) > new Date(c.created)
).length,
replyCount: personalComments.filter(c => c.reply_to_comment_id !== null).length
};
return summary;
}
// 批量更新个人评论模板
async batchUpdateWithTemplate(commentIds: string[], template: string, variables?: Record<string, any>) {
const results = [];
for (const commentId of commentIds) {
try {
// 检查权限
const detailResponse = await this.userClient.getCommentById(commentId);
const comment = detailResponse.data.comment;
if (comment.create_user.user_id !== "user_self") {
results.push({
commentId,
success: false,
error: "无权编辑其他用户的评论"
});
continue;
}
// 应用模板
let newContent = template;
if (variables) {
Object.keys(variables).forEach(key => {
newContent = newContent.replace(new RegExp(`\\{${key}\\}`, 'g'), variables[key]);
});
}
// 添加时间戳
const timestamp = new Date().toLocaleString('zh-CN');
newContent += `\n\n📝 更新时间: ${timestamp}`;
// 执行更新
const updateRequest = {
update_fields: ["content"],
comment: { content: newContent }
};
await this.userClient.updateCommentById(commentId, updateRequest);
results.push({
commentId,
success: true,
oldContent: comment.content,
newContent: newContent
});
} catch (error) {
results.push({
commentId,
success: false,
error: error.message
});
}
}
return results;
}
// 获取所有评论
private async getAllComments(taskId: string) {
let pageToken: string | undefined = undefined;
let allComments = [];
do {
const response = await this.userClient.getCommentPageList({
resource_id: taskId,
page_size: 100,
page_token: pageToken
});
allComments.push(...response.data.items);
pageToken = response.data.page_token;
} while (pageToken);
return allComments;
}
}
// 使用个人评论管理器
const personalCommentManager = new PersonalCommentManager(feishuUserClient);
// 创建不同类型的评论
const statusComment = await personalCommentManager.createStatusComment(
"task_123",
"进行中",
"已完成前端开发,正在进行接口联调。"
);
const problemComment = await personalCommentManager.createStatusComment(
"task_123",
"问题",
"接口返回数据格式与预期不符,需要后端配合调整。"
);
// 获取个人评论摘要
const summary = await personalCommentManager.getPersonalCommentSummary("task_123");
console.log("个人评论摘要:", summary);
// 批量更新评论(使用模板)
const templateResult = await personalCommentManager.batchUpdateWithTemplate(
["comment_1", "comment_2"],
"【模板更新】{status}\n原内容: {original}\n新进度: {progress}",
{
status: "进度更新",
progress: "已完成80%"
}
);
console.log("批量更新结果:", templateResult);
// 个人评论工作流
async function personalCommentWorkflow(taskId: string) {
console.log("开始个人评论工作流...");
// 1. 创建开始评论
await personalCommentManager.createStatusComment(taskId, "开始", "开始处理任务。");
// 2. 模拟工作过程(实际应用中这里会是真实的工作)
console.log("工作中...");
await new Promise(resolve => setTimeout(resolve, 2000));
// 3. 创建进行中评论
await personalCommentManager.createStatusComment(taskId, "进行中", "已完成50%的工作内容。");
// 4. 模拟完成工作
console.log("继续工作中...");
await new Promise(resolve => setTimeout(resolve, 2000));
// 5. 创建完成评论
await personalCommentManager.createStatusComment(taskId, "完成", "任务已全部完成,请审核。");
// 6. 获取最终摘要
const finalSummary = await personalCommentManager.getPersonalCommentSummary(taskId);
console.log("工作流完成,最终评论摘要:", finalSummary);
}
// 运行工作流
// await personalCommentWorkflow("task_123");