From d7f5da5df46cf0ae041e5d84e7a13fe309d5b792 Mon Sep 17 00:00:00 2001 From: hjlarry Date: Mon, 15 Sep 2025 11:41:06 +0800 Subject: [PATCH] display comments avatar on the canvas --- api/fields/workflow_comment_fields.py | 4 +- web/app/components/workflow/comment/icon.tsx | 22 +++++-- .../workflow/hooks/use-workflow-comment.ts | 29 +++++++- web/service/workflow-comment.ts | 66 ++++++++++++++----- 4 files changed, 94 insertions(+), 27 deletions(-) diff --git a/api/fields/workflow_comment_fields.py b/api/fields/workflow_comment_fields.py index 1506147312..d1530b5c5f 100644 --- a/api/fields/workflow_comment_fields.py +++ b/api/fields/workflow_comment_fields.py @@ -1,6 +1,6 @@ from flask_restful import fields -from libs.helper import TimestampField +from libs.helper import AvatarUrlField, TimestampField # Basic account fields for comment creators/resolvers comment_account_fields = {"id": fields.String, "name": fields.String, "email": fields.String} @@ -26,7 +26,7 @@ workflow_comment_participant_fields = { "id": fields.String, "name": fields.String, "email": fields.String, - "avatar": fields.String, + "avatar_url": AvatarUrlField, } # Basic comment fields (for list views) diff --git a/web/app/components/workflow/comment/icon.tsx b/web/app/components/workflow/comment/icon.tsx index a183145421..3aecc7976d 100644 --- a/web/app/components/workflow/comment/icon.tsx +++ b/web/app/components/workflow/comment/icon.tsx @@ -1,16 +1,17 @@ import type { FC } from 'react' import { memo } from 'react' -import type { WorkflowComment } from '@/service/workflow-comment' +import Avatar from '@/app/components/base/avatar' +import type { WorkflowCommentList } from '@/service/workflow-comment' type CommentIconProps = { - comment: WorkflowComment + comment: WorkflowCommentList onClick: () => void } export const CommentIcon: FC = memo(({ comment, onClick }) => { return (
= memo(({ comment, onClick }) => }} onClick={onClick} > -
- {'A'} +
+
+
+
+ +
+
+
) diff --git a/web/app/components/workflow/hooks/use-workflow-comment.ts b/web/app/components/workflow/hooks/use-workflow-comment.ts index 8bfb5c31f0..97cf8ac582 100644 --- a/web/app/components/workflow/hooks/use-workflow-comment.ts +++ b/web/app/components/workflow/hooks/use-workflow-comment.ts @@ -1,9 +1,9 @@ -import { useCallback, useState } from 'react' +import { useCallback, useEffect, useState } from 'react' import { useParams } from 'next/navigation' import { useStore } from '../store' import { ControlMode } from '../types' import type { WorkflowComment } from '@/service/workflow-comment' -import { createWorkflowComment } from '@/service/workflow-comment' +import { createWorkflowComment, fetchWorkflowComments } from '@/service/workflow-comment' export const useWorkflowComment = () => { const params = useParams() @@ -13,6 +13,29 @@ export const useWorkflowComment = () => { const pendingComment = useStore(s => s.pendingComment) const setPendingComment = useStore(s => s.setPendingComment) const [comments, setComments] = useState([]) + const [loading, setLoading] = useState(false) + + // 加载评论列表 + const loadComments = useCallback(async () => { + if (!appId) return + + setLoading(true) + try { + const commentsData = await fetchWorkflowComments(appId) + setComments(commentsData) + } + catch (error) { + console.error('Failed to fetch comments:', error) + } + finally { + setLoading(false) + } + }, [appId]) + + // 初始化时加载评论 + useEffect(() => { + loadComments() + }, [loadComments]) const handleCommentSubmit = useCallback(async (content: string) => { if (!pendingComment) return @@ -77,10 +100,12 @@ export const useWorkflowComment = () => { return { comments, + loading, pendingComment, handleCommentSubmit, handleCommentCancel, handleCommentIconClick, handleCreateComment, + loadComments, } } diff --git a/web/service/workflow-comment.ts b/web/service/workflow-comment.ts index c4d530c63b..856ef6990c 100644 --- a/web/service/workflow-comment.ts +++ b/web/service/workflow-comment.ts @@ -1,26 +1,56 @@ import { del, get, post, put } from './base' import type { CommonResponse } from '@/models/common' -export type WorkflowComment = { +export type UserProfile = { + id: string + name: string + email: string + avatar_url?: string +} + +export type WorkflowCommentList = { id: string - app_id: string position_x: number position_y: number content: string created_by: string + created_by_account: UserProfile created_at: string updated_at: string resolved: boolean resolved_by?: string + resolved_by_account?: UserProfile resolved_at?: string - mentioned_user_ids: string[] - replies_count: number - author: { - id: string - name: string - email: string - avatar?: string - } + mention_count: number + reply_count: number + participants: UserProfile[] +} + +export type WorkflowCommentDetail = { + id: string + position_x: number + position_y: number + content: string + created_by: string + created_by_account: UserProfile + created_at: string + updated_at: string + resolved: boolean + resolved_by?: string + resolved_by_account?: UserProfile + resolved_at?: string + replies: [] + mentions: [] +} + +export type WorkflowCommentCreateRes = { + id: string + created_at: string +} + +export type WorkflowCommentUpdateRes = { + id: string + updated_at: string } export type WorkflowCommentReply = { @@ -58,21 +88,21 @@ export type CreateReplyParams = { mentioned_user_ids?: string[] } -export const fetchWorkflowComments = async (appId: string): Promise => { - const response = await get<{ data: WorkflowComment[] }>(`apps/${appId}/workflow/comments`) +export const fetchWorkflowComments = async (appId: string): Promise => { + const response = await get<{ data: WorkflowCommentList[] }>(`apps/${appId}/workflow/comments`) return response.data } -export const createWorkflowComment = async (appId: string, params: CreateCommentParams): Promise => { - return post(`apps/${appId}/workflow/comments`, { body: params }) +export const createWorkflowComment = async (appId: string, params: CreateCommentParams): Promise => { + return post(`apps/${appId}/workflow/comments`, { body: params }) } -export const fetchWorkflowComment = async (appId: string, commentId: string): Promise => { - return get(`apps/${appId}/workflow/comments/${commentId}`) +export const fetchWorkflowComment = async (appId: string, commentId: string): Promise => { + return get(`apps/${appId}/workflow/comments/${commentId}`) } -export const updateWorkflowComment = async (appId: string, commentId: string, params: UpdateCommentParams): Promise => { - return put(`apps/${appId}/workflow/comments/${commentId}`, { body: params }) +export const updateWorkflowComment = async (appId: string, commentId: string, params: UpdateCommentParams): Promise => { + return put(`apps/${appId}/workflow/comments/${commentId}`, { body: params }) } export const deleteWorkflowComment = async (appId: string, commentId: string): Promise => {