From 559504a73d0d58eb7ea1a0d4ff8fd9d4e37fb5c4 Mon Sep 17 00:00:00 2001 From: wangjiahao <1522128093@qq.com> Date: Thu, 27 Nov 2025 16:07:02 +0800 Subject: [PATCH] feat:Support quick questioning, no need to input questions, can also quickly ask common questions --- backend/apps/chat/api/chat.py | 6 +- backend/apps/chat/curd/chat.py | 16 +++ frontend/src/api/chat.ts | 3 + .../src/assets/svg/icon_quick_question.svg | 1 + frontend/src/i18n/en.json | 3 + frontend/src/i18n/ko-KR.json | 3 + frontend/src/i18n/zh-CN.json | 3 + frontend/src/views/chat/QuickQuestion.vue | 124 ++++++++++++++++++ frontend/src/views/chat/RecentQuestion.vue | 95 ++++++++++++++ frontend/src/views/chat/RecommendQuestion.vue | 25 +++- frontend/src/views/chat/index.vue | 73 ++++++++--- 11 files changed, 334 insertions(+), 18 deletions(-) create mode 100644 frontend/src/assets/svg/icon_quick_question.svg create mode 100644 frontend/src/views/chat/QuickQuestion.vue create mode 100644 frontend/src/views/chat/RecentQuestion.vue diff --git a/backend/apps/chat/api/chat.py b/backend/apps/chat/api/chat.py index dc446685..1d4815fe 100644 --- a/backend/apps/chat/api/chat.py +++ b/backend/apps/chat/api/chat.py @@ -10,7 +10,7 @@ from apps.chat.curd.chat import list_chats, get_chat_with_records, create_chat, rename_chat, \ delete_chat, get_chat_chart_data, get_chat_predict_data, get_chat_with_records_with_data, get_chat_record_by_id, \ - format_json_data, format_json_list_data, get_chart_config + format_json_data, format_json_list_data, get_chart_config, list_recent_questions from apps.chat.models.chat_model import CreateChat, ChatRecord, RenameChat, ChatQuestion, AxisObj from apps.chat.task.llm import LLMService from common.core.deps import CurrentAssistant, SessionDep, CurrentUser, Trans @@ -132,6 +132,10 @@ def _err(_e: Exception): return StreamingResponse(llm_service.await_result(), media_type="text/event-stream") +@router.get("/recent_questions/{datasource_id}") +async def recommend_questions(session: SessionDep, current_user: CurrentUser, datasource_id: int): + return list_recent_questions(session=session, current_user=current_user, datasource_id=datasource_id) + @router.post("/question") async def stream_sql(session: SessionDep, current_user: CurrentUser, request_question: ChatQuestion, diff --git a/backend/apps/chat/curd/chat.py b/backend/apps/chat/curd/chat.py index 034c4287..0872c6f4 100644 --- a/backend/apps/chat/curd/chat.py +++ b/backend/apps/chat/curd/chat.py @@ -1,5 +1,6 @@ import datetime from typing import List +from sqlalchemy import desc, func import orjson import sqlparse @@ -35,6 +36,21 @@ def list_chats(session: SessionDep, current_user: CurrentUser) -> List[Chat]: return chart_list +def list_recent_questions(session: SessionDep, current_user: CurrentUser, datasource_id: int) -> List[str]: + chat_records = ( + session.query(ChatRecord.question) + .filter( + ChatRecord.datasource == datasource_id, + ChatRecord.question.isnot(None) + ) + .group_by(ChatRecord.question) + .order_by(desc(func.max(ChatRecord.create_time))) + .limit(10) + .all() + ) + return [record[0] for record in chat_records] if chat_records else [] + + def rename_chat(session: SessionDep, rename_object: RenameChat) -> str: chat = session.get(Chat, rename_object.id) if not chat: diff --git a/frontend/src/api/chat.ts b/frontend/src/api/chat.ts index affb883a..d840b31e 100644 --- a/frontend/src/api/chat.ts +++ b/frontend/src/api/chat.ts @@ -331,6 +331,9 @@ export const chatApi = { recommendQuestions: (record_id: number | undefined, controller?: AbortController) => { return request.fetchStream(`/chat/recommend_questions/${record_id}`, {}, controller) }, + recentQuestions: (datasource_id?: number): Promise => { + return request.get(`/chat/recent_questions/${datasource_id}`) + }, checkLLMModel: () => request.get('/system/aimodel/default', { requestOptions: { silent: true } }), export2Excel: (record_id: number | undefined) => request.get(`/chat/record/${record_id}/excel/export`, { diff --git a/frontend/src/assets/svg/icon_quick_question.svg b/frontend/src/assets/svg/icon_quick_question.svg new file mode 100644 index 00000000..dbfdebce --- /dev/null +++ b/frontend/src/assets/svg/icon_quick_question.svg @@ -0,0 +1 @@ + diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index 7772e794..c6fbf91a 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -184,6 +184,9 @@ "chart_selected": "Selected {0}" }, "qa": { + "recently": "recently", + "recommend": "recommend", + "quick_question": "quick question", "new_chat": "New Chat", "start_sqlbot": "New Chat", "title": "Data Q&A", diff --git a/frontend/src/i18n/ko-KR.json b/frontend/src/i18n/ko-KR.json index cb149dd5..343c5080 100644 --- a/frontend/src/i18n/ko-KR.json +++ b/frontend/src/i18n/ko-KR.json @@ -184,6 +184,9 @@ "chart_selected": "{0}개 선택됨" }, "qa": { + "recently": "최근", + "recommend": "추천", + "quick_question": "빠른 질문", "new_chat": "새 대화 생성", "start_sqlbot": "데이터 조회 시작", "title": "스마트 데이터 조회", diff --git a/frontend/src/i18n/zh-CN.json b/frontend/src/i18n/zh-CN.json index 0897aa9a..19a918a6 100644 --- a/frontend/src/i18n/zh-CN.json +++ b/frontend/src/i18n/zh-CN.json @@ -184,6 +184,9 @@ "chart_selected": "已选{0}" }, "qa": { + "recently": "最近", + "recommend": "推荐", + "quick_question": "快捷提问", "new_chat": "新建对话", "start_sqlbot": "开启问数", "title": "智能问数", diff --git a/frontend/src/views/chat/QuickQuestion.vue b/frontend/src/views/chat/QuickQuestion.vue new file mode 100644 index 00000000..cd68babb --- /dev/null +++ b/frontend/src/views/chat/QuickQuestion.vue @@ -0,0 +1,124 @@ + + + + + diff --git a/frontend/src/views/chat/RecentQuestion.vue b/frontend/src/views/chat/RecentQuestion.vue new file mode 100644 index 00000000..6b0d74c9 --- /dev/null +++ b/frontend/src/views/chat/RecentQuestion.vue @@ -0,0 +1,95 @@ + + + + + diff --git a/frontend/src/views/chat/RecommendQuestion.vue b/frontend/src/views/chat/RecommendQuestion.vue index 5acb9012..1cc56b6a 100644 --- a/frontend/src/views/chat/RecommendQuestion.vue +++ b/frontend/src/views/chat/RecommendQuestion.vue @@ -11,6 +11,7 @@ const props = withDefaults( questions?: string firstChat?: boolean disabled?: boolean + position?: string }>(), { recordId: undefined, @@ -18,6 +19,7 @@ const props = withDefaults( questions: '[]', firstChat: false, disabled: false, + position: 'chat', } ) @@ -153,11 +155,24 @@ defineExpose({ getRecommendQuestions, id: () => props.recordId, stop })