Skip to content

Commit 9dccaf1

Browse files
authored
feat(dashboard): The dashboard supports displaying real-time data (#930)
1 parent d12cb83 commit 9dccaf1

File tree

10 files changed

+65
-8
lines changed

10 files changed

+65
-8
lines changed

backend/apps/chat/api/chat.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
list_chats, get_chat_with_records, create_chat, rename_chat, \
1515
delete_chat, get_chat_chart_data, get_chat_predict_data, get_chat_with_records_with_data, get_chat_record_by_id, \
1616
format_json_data, format_json_list_data, get_chart_config, list_recent_questions, get_chat as get_chat_exec, \
17-
rename_chat_with_user, get_chat_log_history
17+
rename_chat_with_user, get_chat_log_history, get_chart_data_with_user_live
1818
from apps.chat.models.chat_model import CreateChat, ChatRecord, RenameChat, ChatQuestion, AxisObj, QuickCommand, \
1919
ChatInfo, Chat, ChatFinishStep
2020
from apps.chat.task.llm import LLMService
@@ -80,6 +80,13 @@ def inner():
8080

8181
return await asyncio.to_thread(inner)
8282

83+
@router.get("/record/{chat_record_id}/data_live", summary=f"{PLACEHOLDER_PREFIX}get_chart_data_live")
84+
async def chat_record_data_live(session: SessionDep, current_user: CurrentUser, chat_record_id: int):
85+
def inner():
86+
data = get_chart_data_with_user_live(chat_record_id=chat_record_id, session=session, current_user=current_user)
87+
return format_json_data(data)
88+
89+
return await asyncio.to_thread(inner)
8390

8491
@router.get("/record/{chat_record_id}/predict_data", summary=f"{PLACEHOLDER_PREFIX}get_chart_predict_data")
8592
async def chat_predict_data(session: SessionDep, current_user: CurrentUser, chat_record_id: int):

backend/apps/chat/curd/chat.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@
99

1010
from apps.chat.models.chat_model import Chat, ChatRecord, CreateChat, ChatInfo, RenameChat, ChatQuestion, ChatLog, \
1111
TypeEnum, OperationEnum, ChatRecordResult, ChatLogHistory, ChatLogHistoryItem
12+
from apps.datasource.crud.datasource import get_ds
1213
from apps.datasource.crud.recommended_problem import get_datasource_recommended_chart
1314
from apps.datasource.models.datasource import CoreDatasource
1415
from apps.db.constant import DB
16+
from apps.db.db import exec_sql
1517
from apps.system.crud.assistant import AssistantOutDs, AssistantOutDsFactory
1618
from apps.system.schemas.system_schema import AssistantOutDsSchema
1719
from common.core.deps import CurrentAssistant, SessionDep, CurrentUser, Trans
20+
from common.utils.data_format import DataFormat
1821
from common.utils.utils import extract_nested_json
1922

2023

@@ -234,6 +237,20 @@ def get_chart_data_with_user(session: SessionDep, current_user: CurrentUser, cha
234237
pass
235238
return {}
236239

240+
def get_chart_data_with_user_live(session: SessionDep, current_user: CurrentUser, chat_record_id: int):
241+
stmt = select(ChatRecord.datasource,ChatRecord.sql).where(and_(ChatRecord.id == chat_record_id, ChatRecord.create_by == current_user.id))
242+
row = session.execute(stmt).first()
243+
return get_chart_data_ds(session,row.datasource, row.sql)
244+
245+
def get_chart_data_ds(session: SessionDep,ds_id,sql):
246+
try:
247+
datasource = get_ds(session,ds_id)
248+
result = exec_sql(ds=datasource,sql=sql, origin_column=False)
249+
_data = DataFormat.convert_large_numbers_in_object_array(result.get('data'))
250+
return _data
251+
except Exception:
252+
pass
253+
return []
237254

238255
def get_chat_chart_data(session: SessionDep, chat_record_id: int):
239256
stmt = select(ChatRecord.data).where(and_(ChatRecord.id == chat_record_id))
@@ -307,7 +324,7 @@ def get_chat_with_records(session: SessionDep, chart_id: int, current_user: Curr
307324
predict_alias_log = aliased(ChatLog)
308325

309326
stmt = (select(ChatRecord.id, ChatRecord.chat_id, ChatRecord.create_time, ChatRecord.finish_time,
310-
ChatRecord.question, ChatRecord.sql_answer, ChatRecord.sql,
327+
ChatRecord.question, ChatRecord.sql_answer, ChatRecord.sql,ChatRecord.datasource,
311328
ChatRecord.chart_answer, ChatRecord.chart, ChatRecord.analysis, ChatRecord.predict,
312329
ChatRecord.datasource_select_answer, ChatRecord.analysis_record_id, ChatRecord.predict_record_id,
313330
ChatRecord.regenerate_record_id,
@@ -334,7 +351,7 @@ def get_chat_with_records(session: SessionDep, chart_id: int, current_user: Curr
334351
ChatRecord.create_time))
335352
if with_data:
336353
stmt = select(ChatRecord.id, ChatRecord.chat_id, ChatRecord.create_time, ChatRecord.finish_time,
337-
ChatRecord.question, ChatRecord.sql_answer, ChatRecord.sql,
354+
ChatRecord.question, ChatRecord.sql_answer, ChatRecord.sql,ChatRecord.datasource,
338355
ChatRecord.chart_answer, ChatRecord.chart, ChatRecord.analysis, ChatRecord.predict,
339356
ChatRecord.datasource_select_answer, ChatRecord.analysis_record_id, ChatRecord.predict_record_id,
340357
ChatRecord.regenerate_record_id,
@@ -400,7 +417,7 @@ def get_chat_with_records(session: SessionDep, chart_id: int, current_user: Curr
400417
finish_time=row.finish_time,
401418
duration=duration,
402419
total_tokens=total_tokens,
403-
question=row.question, sql_answer=row.sql_answer, sql=row.sql,
420+
question=row.question, sql_answer=row.sql_answer, sql=row.sql, datasource=row.datasource,
404421
chart_answer=row.chart_answer, chart=row.chart,
405422
analysis=row.analysis, predict=row.predict,
406423
datasource_select_answer=row.datasource_select_answer,
@@ -419,7 +436,7 @@ def get_chat_with_records(session: SessionDep, chart_id: int, current_user: Curr
419436
finish_time=row.finish_time,
420437
duration=duration,
421438
total_tokens=total_tokens,
422-
question=row.question, sql_answer=row.sql_answer, sql=row.sql,
439+
question=row.question, sql_answer=row.sql_answer, sql=row.sql, datasource=row.datasource,
423440
chart_answer=row.chart_answer, chart=row.chart,
424441
analysis=row.analysis, predict=row.predict,
425442
datasource_select_answer=row.datasource_select_answer,

backend/apps/chat/models/chat_model.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ class ChatRecordResult(BaseModel):
140140
question: Optional[str] = None
141141
sql_answer: Optional[str] = None
142142
sql: Optional[str] = None
143+
datasource: Optional[int] = None
143144
data: Optional[str] = None
144145
chart_answer: Optional[str] = None
145146
chart: Optional[str] = None

backend/apps/chat/task/llm.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,7 @@ def save_sql_data(self, session: Session, data_obj: Dict[str, Any]):
10051005
data_obj['limit'] = limit
10061006
else:
10071007
data_obj['data'] = data_result
1008+
data_obj['datasource'] = self.ds.id
10081009
return save_sql_exec_data(session=session, record_id=self.record.id,
10091010
data=orjson.dumps(data_obj).decode())
10101011
except Exception as e:

backend/apps/dashboard/crud/dashboard_service.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1+
import base64
2+
3+
from orjson import orjson
14
from sqlalchemy import select, and_, text
5+
6+
from apps.chat.curd.chat import get_chart_data_ds
27
from apps.dashboard.models.dashboard_model import CoreDashboard, CreateDashboard, QueryDashboard, DashboardBaseResponse
38
from common.core.deps import SessionDep, CurrentUser
49
import uuid
@@ -27,7 +32,7 @@ def list_resource(session: SessionDep, dashboard: QueryDashboard, current_user:
2732
nodes = [DashboardBaseResponse(**row) for row in result.mappings()]
2833
tree = build_tree_generic(nodes, root_pid="root")
2934
return tree
30-
35+
3136

3237
def load_resource(session: SessionDep, dashboard: QueryDashboard):
3338
sql = text("""
@@ -41,7 +46,16 @@ def load_resource(session: SessionDep, dashboard: QueryDashboard):
4146
WHERE cd.id = :dashboard_id
4247
""")
4348
result = session.execute(sql, {"dashboard_id": dashboard.id}).mappings().first()
44-
return result
49+
50+
result_dict = dict(result)
51+
canvas_view_obj = orjson.loads(result_dict['canvas_view_info'])
52+
for item in canvas_view_obj.values(): # 直接遍历值
53+
# 检查必要字段是否存在
54+
if all(key in item for key in ['datasource', 'sql']) and item['datasource'] is not None:
55+
item['data']['data'] = get_chart_data_ds(session, item['datasource'], item['sql'])
56+
57+
result_dict['canvas_view_info'] = orjson.dumps(canvas_view_obj)
58+
return result_dict
4559

4660

4761
def get_create_base_info(user: CurrentUser, dashboard: CreateDashboard):

backend/apps/swagger/locales/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
"get_chat": "Get Chat Details",
141141
"get_chat_with_data": "Get Chat Details (With Data)",
142142
"get_chart_data": "Get Chart Data",
143+
"get_chart_data_live": "Get Chart Data Live",
143144
"get_chart_predict_data": "Get Chart Prediction Data",
144145
"get_record_log": "Get Chart Record Log",
145146
"get_record_usage": "Get Chart Record Token Usage & Duration",

backend/apps/swagger/locales/zh.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
"get_chat": "获取对话详情",
141141
"get_chat_with_data": "获取对话详情(带数据)",
142142
"get_chart_data": "获取图表数据",
143+
"get_chart_data_live": "获取图表实时数据",
143144
"get_chart_predict_data": "获取图表预测数据",
144145
"get_record_log": "获取对话日志",
145146
"get_record_usage": "获取对话Token使用量及耗时",

frontend/src/api/chat.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export class ChatRecord {
3939
question?: string
4040
sql_answer?: string
4141
sql?: string
42+
datasource?: number
4243
data?: string | any
4344
chart_answer?: string
4445
chart?: string
@@ -67,6 +68,7 @@ export class ChatRecord {
6768
question: string,
6869
sql_answer: string | undefined,
6970
sql: string | undefined,
71+
datasource: number | undefined,
7072
data: string | any | undefined,
7173
chart_answer: string | undefined,
7274
chart: string | undefined,
@@ -94,6 +96,7 @@ export class ChatRecord {
9496
question?: string,
9597
sql_answer?: string,
9698
sql?: string,
99+
datasource?: number | undefined,
97100
data?: string | any,
98101
chart_answer?: string,
99102
chart?: string,
@@ -120,6 +123,7 @@ export class ChatRecord {
120123
this.question = question
121124
this.sql_answer = sql_answer
122125
this.sql = sql
126+
this.datasource = datasource
123127
this.data = data
124128
this.chart_answer = chart_answer
125129
this.chart = chart
@@ -263,6 +267,7 @@ const toChatRecord = (data?: any): ChatRecord | undefined => {
263267
data.question,
264268
data.sql_answer,
265269
data.sql,
270+
data.datasource,
266271
data.data,
267272
data.chart_answer,
268273
data.chart,

frontend/src/views/chat/chat-block/ChartBlock.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ const dataObject = computed<{
5555
fields: Array<string>
5656
data: Array<{ [key: string]: any }>
5757
limit: number | undefined
58+
datasource: number | undefined
59+
sql: string | undefined
5860
}>(() => {
5961
if (props.message?.record?.data) {
6062
if (typeof props.message?.record?.data === 'string') {
@@ -220,6 +222,8 @@ function addToDashboard() {
220222
data: {
221223
data: data.value,
222224
},
225+
sql: props.message?.record?.sql,
226+
datasource: props.message?.record?.datasource,
223227
chart: {},
224228
}
225229
// @ts-expect-error eslint-disable-next-line @typescript-eslint/ban-ts-comment

frontend/src/views/dashboard/editor/ChatChartSelection.vue

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,13 @@ function adaptorChartInfoList(chatInfo: ChatInfo) {
143143
record?.predict_record_id !== null &&
144144
data?.data?.length > 0)
145145
) {
146-
const recordeInfo = { id: chatInfo.id + '_' + record.id, data: data, chart: {} }
146+
const recordeInfo = {
147+
id: chatInfo.id + '_' + record.id,
148+
sql: record.sql,
149+
datasource: record.datasource,
150+
data: data,
151+
chart: {},
152+
}
147153
const chartBaseInfo = JSON.parse(record.chart)
148154
if (chartBaseInfo) {
149155
let yAxis = []

0 commit comments

Comments
 (0)