From 02dff554ac94ad71dd0e5b48ddd2f110edc29cfb Mon Sep 17 00:00:00 2001 From: Wenjie Zhang Date: Wed, 8 Oct 2025 22:36:35 +0800 Subject: [PATCH] =?UTF-8?q?feat(dashboard):=20=E5=A2=9E=E5=BC=BA=E5=8F=8D?= =?UTF-8?q?=E9=A6=88=E5=88=97=E8=A1=A8=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在反馈列表中新增用户的用户名和头像字段 - 更新后端接口以支持根据智能体ID过滤反馈记录 - 前端实现反馈详情模态框,提升用户交互体验 - 优化反馈数据的查询逻辑,确保隐私合规性 --- server/routers/dashboard_router.py | 30 +- web/src/apis/dashboard_api.js | 6 +- .../dashboard/FeedbackModalComponent.vue | 411 ++++++++++++++++++ web/src/views/AgentView.vue | 15 +- web/src/views/DashboardView.vue | 144 +----- 5 files changed, 455 insertions(+), 151 deletions(-) create mode 100644 web/src/components/dashboard/FeedbackModalComponent.vue diff --git a/server/routers/dashboard_router.py b/server/routers/dashboard_router.py index 393589cf..a48b88cf 100644 --- a/server/routers/dashboard_router.py +++ b/server/routers/dashboard_router.py @@ -638,6 +638,8 @@ class FeedbackListItem(BaseModel): id: int user_id: str + username: str | None + avatar: str | None rating: str reason: str | None created_at: str @@ -649,36 +651,48 @@ class FeedbackListItem(BaseModel): @dashboard.get("/feedbacks", response_model=list[FeedbackListItem]) async def get_all_feedbacks( rating: str | None = None, - limit: int = 100, - offset: int = 0, + agent_id: str | None = None, db: Session = Depends(get_db), current_user: User = Depends(get_admin_user), ): """Get all feedback records (Admin only)""" - from src.storage.db.models import MessageFeedback, Message, Conversation + from src.storage.db.models import MessageFeedback, Message, Conversation, User try: - # Build query with joins + # Build query with joins including User table + # Try both User.id and User.user_id as MessageFeedback.user_id might be stored as either query = ( - db.query(MessageFeedback, Message, Conversation) + db.query(MessageFeedback, Message, Conversation, User) .join(Message, MessageFeedback.message_id == Message.id) .join(Conversation, Message.conversation_id == Conversation.id) + .outerjoin(User, + (MessageFeedback.user_id == User.id) | + (MessageFeedback.user_id == User.user_id) + ) ) # Apply filters if rating and rating in ["like", "dislike"]: query = query.filter(MessageFeedback.rating == rating) + if agent_id: + query = query.filter(Conversation.agent_id == agent_id) - # Order and paginate - query = query.order_by(MessageFeedback.created_at.desc()).limit(limit).offset(offset) + # Order by creation time (most recent first) + query = query.order_by(MessageFeedback.created_at.desc()) results = query.all() + # Debug logging (privacy-safe) + logger.info(f"Found {len(results)} feedback records") + # Removed sensitive user data from logs for privacy compliance + return [ { "id": feedback.id, "message_id": feedback.message_id, "user_id": feedback.user_id, + "username": user.username if user else None, + "avatar": user.avatar if user else None, "rating": feedback.rating, "reason": feedback.reason, "created_at": feedback.created_at.isoformat(), @@ -686,7 +700,7 @@ async def get_all_feedbacks( "conversation_title": conversation.title, "agent_id": conversation.agent_id, } - for feedback, message, conversation in results + for feedback, message, conversation, user in results ] except Exception as e: logger.error(f"Error getting feedbacks: {e}") diff --git a/web/src/apis/dashboard_api.js b/web/src/apis/dashboard_api.js index 7677fffc..0ae66c7a 100644 --- a/web/src/apis/dashboard_api.js +++ b/web/src/apis/dashboard_api.js @@ -48,15 +48,13 @@ export const dashboardApi = { * 获取用户反馈列表 * @param {Object} params - 查询参数 * @param {string} params.rating - 反馈类型过滤 (like/dislike/all) - * @param {number} params.limit - 每页数量 - * @param {number} params.offset - 偏移量 + * @param {string} params.agent_id - 智能体ID过滤 * @returns {Promise} - 反馈列表 */ getFeedbacks: (params = {}) => { const queryParams = new URLSearchParams() if (params.rating && params.rating !== 'all') queryParams.append('rating', params.rating) - if (params.limit) queryParams.append('limit', params.limit) - if (params.offset) queryParams.append('offset', params.offset) + if (params.agent_id) queryParams.append('agent_id', params.agent_id) return apiAdminGet(`/api/dashboard/feedbacks?${queryParams.toString()}`) }, diff --git a/web/src/components/dashboard/FeedbackModalComponent.vue b/web/src/components/dashboard/FeedbackModalComponent.vue new file mode 100644 index 00000000..616f86e1 --- /dev/null +++ b/web/src/components/dashboard/FeedbackModalComponent.vue @@ -0,0 +1,411 @@ + + + + + diff --git a/web/src/views/AgentView.vue b/web/src/views/AgentView.vue index 67e633fd..13b8022b 100644 --- a/web/src/views/AgentView.vue +++ b/web/src/views/AgentView.vue @@ -18,6 +18,12 @@
配置
+
+ + + 反馈详情 + +
+ + +
@@ -91,19 +100,21 @@ import { LinkOutlined, StarOutlined, StarFilled, + MessageOutlined, } from '@ant-design/icons-vue'; import { message } from 'ant-design-vue'; import { Bot } from 'lucide-vue-next'; import AgentChatComponent from '@/components/AgentChatComponent.vue'; import AgentConfigSidebar from '@/components/AgentConfigSidebar.vue'; +import FeedbackModalComponent from '@/components/dashboard/FeedbackModalComponent.vue'; import { useUserStore } from '@/stores/user'; import { useAgentStore } from '@/stores/agent'; import { useInfoStore } from '@/stores/info'; import { storeToRefs } from 'pinia'; -// 路由和stores -const router = useRouter(); +// 组件引用 +const feedbackModal = ref(null) const userStore = useUserStore(); const agentStore = useAgentStore(); const infoStore = useInfoStore(); diff --git a/web/src/views/DashboardView.vue b/web/src/views/DashboardView.vue index c5e03bac..41c3a134 100644 --- a/web/src/views/DashboardView.vue +++ b/web/src/views/DashboardView.vue @@ -75,7 +75,7 @@ 刷新 - + 反馈详情 @@ -113,56 +113,14 @@ - - - - - 全部 - 点赞 - 点踩 - - - - - - - + +