diff --git a/backend/apps/chat/api/chat.py b/backend/apps/chat/api/chat.py index c1bbae9c..65052a8d 100644 --- a/backend/apps/chat/api/chat.py +++ b/backend/apps/chat/api/chat.py @@ -24,7 +24,7 @@ async def chats(session: SessionDep, current_user: CurrentUser): @router.get("/get/{chart_id}") -async def list_chat(session: SessionDep, current_user: CurrentUser, chart_id: int): +async def get_chat(session: SessionDep, current_user: CurrentUser, chart_id: int): try: return get_chat_with_records(chart_id=chart_id, session=session, current_user=current_user) except Exception as e: diff --git a/backend/apps/chat/curd/chat.py b/backend/apps/chat/curd/chat.py index 774e4967..358040b5 100644 --- a/backend/apps/chat/curd/chat.py +++ b/backend/apps/chat/curd/chat.py @@ -2,6 +2,7 @@ import datetime from typing import List from sqlalchemy import and_ +from sqlalchemy.orm import load_only from apps.chat.models.chat_model import Chat, ChatRecord, CreateChat, ChatInfo, RenameChat, ChatQuestion from apps.datasource.models.datasource import CoreDatasource @@ -55,7 +56,11 @@ def get_chat_with_records(session: SessionDep, chart_id: int, current_user: Curr chat_info.datasource_exists = True chat_info.datasource_name = ds.name - record_list = session.query(ChatRecord).filter( + record_list = session.query(ChatRecord).options( + load_only(ChatRecord.id, ChatRecord.chat_id, ChatRecord.create_time, ChatRecord.finish_time, + ChatRecord.question, ChatRecord.sql_answer, ChatRecord.sql, ChatRecord.data, + ChatRecord.chart_answer, ChatRecord.chart, ChatRecord.finish, ChatRecord.error, + ChatRecord.run_time)).filter( and_(Chat.create_by == current_user.id, ChatRecord.chat_id == chart_id)).order_by(ChatRecord.create_time).all() chat_info.records = record_list @@ -96,6 +101,9 @@ def create_chat(session: SessionDep, current_user: CurrentUser, create_chat_obj: chat_info.id = chat.id session.commit() + chat_info.datasource_exists = True + chat_info.datasource_name = ds.name + return chat_info @@ -214,6 +222,7 @@ def save_error_message(session: SessionDep, record_id: int, message: str) -> Cha record = session.query(ChatRecord).filter(ChatRecord.id == record_id).first() record.error = message record.finish = True + record.finish_time = datetime.datetime.now() result = ChatRecord(**record.model_dump()) @@ -242,11 +251,13 @@ def save_sql_exec_data(session: SessionDep, record_id: int, data: str) -> ChatRe return result + def finish_record(session: SessionDep, record_id: int) -> ChatRecord: if not record_id: raise Exception("Record id cannot be None") record = session.query(ChatRecord).filter(ChatRecord.id == record_id).first() record.finish = True + record.finish_time = datetime.datetime.now() result = ChatRecord(**record.model_dump()) @@ -257,4 +268,3 @@ def finish_record(session: SessionDep, record_id: int) -> ChatRecord: session.commit() return result - diff --git a/backend/apps/chat/models/chat_model.py b/backend/apps/chat/models/chat_model.py index b65af0ad..7687a375 100644 --- a/backend/apps/chat/models/chat_model.py +++ b/backend/apps/chat/models/chat_model.py @@ -2,7 +2,7 @@ from sqlmodel import SQLModel, Field from sqlalchemy import Column, Text, BigInteger, DateTime, Integer, Identity, Boolean from datetime import datetime from pydantic import BaseModel -from typing import List, Optional +from typing import List, Optional, Any from apps.template.generate_chart.generator import get_chart_template from apps.template.generate_sql.generator import get_sql_template diff --git a/backend/apps/datasource/api/datasource.py b/backend/apps/datasource/api/datasource.py index 52b515b7..bec379b5 100644 --- a/backend/apps/datasource/api/datasource.py +++ b/backend/apps/datasource/api/datasource.py @@ -9,10 +9,10 @@ from fastapi import APIRouter, File, UploadFile, HTTPException from apps.db.engine import create_table, get_data_engine, insert_data from common.core.deps import SessionDep, CurrentUser from ..crud.datasource import get_datasource_list, check_status, create_ds, update_ds, delete_ds, getTables, getFields, \ - execSql, update_table_and_fields, getTablesByDs, chooseTables, preview + execSql, update_table_and_fields, getTablesByDs, chooseTables, preview, updateTable, updateField from ..crud.field import get_fields_by_table_id from ..crud.table import get_tables_by_ds_id -from ..models.datasource import CoreDatasource, CreateDatasource, TableObj, CoreTable +from ..models.datasource import CoreDatasource, CreateDatasource, TableObj, CoreTable, CoreField router = APIRouter(tags=["datasource"], prefix="/datasource") path = "/opt/sqlbot/data/excel" @@ -83,6 +83,16 @@ async def edit_local(session: SessionDep, data: TableObj): update_table_and_fields(session, data) +@router.post("/editTable") +async def edit_table(session: SessionDep, table: CoreTable): + updateTable(session, table) + + +@router.post("/editField") +async def edit_field(session: SessionDep, field: CoreField): + updateField(session, field) + + @router.post("/previewData/{id}") async def edit_local(session: SessionDep, id: int, data: TableObj): return preview(session, id, data) diff --git a/backend/apps/datasource/crud/datasource.py b/backend/apps/datasource/crud/datasource.py index 1e1b597f..37d83a27 100644 --- a/backend/apps/datasource/crud/datasource.py +++ b/backend/apps/datasource/crud/datasource.py @@ -192,6 +192,14 @@ def update_table_and_fields(session: SessionDep, data: TableObj): update_field(session, field) +def updateTable(session: SessionDep, table: CoreTable): + update_table(session, table) + + +def updateField(session: SessionDep, field: CoreField): + update_field(session, field) + + def preview(session: SessionDep, id: int, data: TableObj): ds = session.query(CoreDatasource).filter(CoreDatasource.id == id).first() conf = DatasourceConf(**json.loads(aes_decrypt(ds.configuration))) if ds.type != "excel" else get_engine_config() @@ -225,6 +233,8 @@ def get_table_obj_by_ds(session: SessionDep, ds: CoreDatasource) -> List[TableAn def get_table_schema(session: SessionDep, ds: CoreDatasource) -> str: schema_str = "" table_objs = get_table_obj_by_ds(session=session, ds=ds) + if len(table_objs) == 0: + return schema_str db_name = table_objs[0].schema schema_str += f"【DB_ID】 {db_name}\n【Schema】\n" for obj in table_objs: diff --git a/backend/apps/db/engine.py b/backend/apps/db/engine.py index 055ea79e..4bfc7b54 100644 --- a/backend/apps/db/engine.py +++ b/backend/apps/db/engine.py @@ -12,7 +12,7 @@ from common.core.config import settings def get_engine_config(): return DatasourceConf(username=settings.POSTGRES_USER, password=settings.POSTGRES_PASSWORD, - host="127.0.0.1", port=settings.POSTGRES_PORT, database=settings.POSTGRES_DB, + host=settings.POSTGRES_SERVER, port=settings.POSTGRES_PORT, database=settings.POSTGRES_DB, dbSchema="public") diff --git a/frontend/src/api/chat.ts b/frontend/src/api/chat.ts index 8234805f..8660b22d 100644 --- a/frontend/src/api/chat.ts +++ b/frontend/src/api/chat.ts @@ -20,6 +20,7 @@ export interface ChatMessage { role: 'user' | 'assistant' create_time?: Date | string content?: string | number + record?: ChatRecord isTyping?: boolean isWelcome?: boolean } @@ -28,24 +29,32 @@ export class ChatRecord { id?: number chat_id?: number create_time?: Date | string - create_by?: number - datasource?: number - engine_type?: string + finish_time?: Date | string question?: string - answer?: string + sql_answer?: string + sql?: string + data?: string + chart_answer?: string + chart?: string + finish?: boolean = false + error?: string run_time: number = 0 constructor() - constructor(id: number, chat_id: number, create_time: Date | string, create_by: number, datasource: number, engine_type: string, question: string, answer: string, run_time: number) - constructor(id?: number, chat_id?: number, create_time?: Date | string, create_by?: number, datasource?: number, engine_type?: string, question?: string, answer?: string, run_time?: number) { + constructor(id: number, chat_id: number, create_time: Date | string, finish_time: Date | string | undefined, question: string, sql_answer: string | undefined, sql: string | undefined, data: string | undefined, chart_answer: string | undefined, chart: string | undefined, finish: boolean, error: string | undefined, run_time: number) + constructor(id?: number, chat_id?: number, create_time?: Date | string, finish_time?: Date | string, question?: string, sql_answer?: string, sql?: string, data?: string, chart_answer?: string, chart?: string, finish?: boolean, error?: string, run_time?: number) { this.id = id this.chat_id = chat_id this.create_time = getDate(create_time) - this.create_by = create_by - this.datasource = datasource - this.engine_type = engine_type + this.finish_time = getDate(finish_time) this.question = question - this.answer = answer + this.sql_answer = sql_answer + this.sql = sql + this.data = data + this.chart_answer = chart_answer + this.chart = chart + this.finish = finish + this.error = error this.run_time = run_time ?? 0 } } @@ -111,7 +120,7 @@ function toChatRecord(data?: any): ChatRecord | undefined { if (!data) { return undefined } - return new ChatRecord(data.id, data.number, data.create_time, data.create_by, data.datasource, data.engine_type, data.question, data.answer, data.run_time) + return new ChatRecord(data.id, data.chat_id, data.create_time, data.finish_time, data.question, data.sql_answer, data.sql, data.data, data.chart_answer, data.chart, data.finish, data.error, data.run_time) } function toChatRecordList(list: any = []): ChatRecord[] { diff --git a/frontend/src/api/datasource.ts b/frontend/src/api/datasource.ts index 1240e45d..64c86355 100644 --- a/frontend/src/api/datasource.ts +++ b/frontend/src/api/datasource.ts @@ -15,4 +15,6 @@ export const datasourceApi = { fieldList: (id: Number) => request.post(`/datasource/fieldList/${id}`), edit: (data: any) => request.post('/datasource/editLocalComment', data), previewData: (id: Number, data: any) => request.post(`/datasource/previewData/${id}`, data), + saveTable: (data: any) => request.post('/datasource/editTable', data), + saveField: (data: any) => request.post('/datasource/editField', data) } \ No newline at end of file diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index 5bbaa554..d26a47ca 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -7,7 +7,7 @@ import chat from "@/views/chat/index.vue"; import ds from "@/views/ds/index.vue"; import DashboardEditor from "@/views/dashboard/editor/index.vue"; import Dashboard from "@/views/dashboard/index.vue"; -import setting from "@/views/setting/index.vue"; +// import setting from "@/views/setting/index.vue"; import { watchRouter } from "./watch"; const router = createRouter({ history: createWebHashHistory(), @@ -81,7 +81,7 @@ const router = createRouter({ }, ], }, - { + /* { path: "/setting", component: Layout, redirect: "/setting/index", @@ -93,7 +93,7 @@ const router = createRouter({ meta: { title: "Settings", icon: "setting" }, }, ], - }, + }, */ { path: "/system", component: Layout, diff --git a/frontend/src/views/chat/index.vue b/frontend/src/views/chat/index.vue index db5f0de8..cf80f458 100644 --- a/frontend/src/views/chat/index.vue +++ b/frontend/src/views/chat/index.vue @@ -1,18 +1,25 @@ diff --git a/frontend/src/views/ds/TableList.vue b/frontend/src/views/ds/TableList.vue index 0be405a7..56d1a889 100644 --- a/frontend/src/views/ds/TableList.vue +++ b/frontend/src/views/ds/TableList.vue @@ -5,7 +5,7 @@ {{ props.dsName }} - Save +
@@ -43,7 +43,8 @@ {{ currentTable.table_name }} Comment: - + {{ currentTable.custom_comment }} +
@@ -89,6 +91,48 @@ + + +
Table Comment
+ + +
+ Cancel + Confirm +
+
+ + +
Field Comment
+ + +
+ Cancel + Confirm +
+
@@ -98,6 +142,7 @@ import { datasourceApi } from "@/api/datasource"; import { onMounted } from "vue"; import { ArrowLeft } from "@element-plus/icons-vue"; import type { TabsPaneContext } from "element-plus-secondary"; +import IconOpeEdit from '@/assets/svg/operate/ope-edit.svg' const props = defineProps({ dsId: { type: [Number], required: true }, @@ -108,10 +153,13 @@ const dsId = ref(0); const searchValue = ref(""); const tableList = ref([]); const currentTable = ref({}); +const currentField = ref({}); const fieldList = ref([]); const previewData = ref({}); const activeName = ref("schema"); +const tableDialog = ref(false) +const fieldDialog = ref(false) const buildData = () => { return { table: currentTable.value, fields: fieldList.value }; @@ -121,15 +169,59 @@ const back = () => { history.back(); }; -const save = () => { - datasourceApi.edit(buildData()).then(() => { +// const save = () => { +// datasourceApi.edit(buildData()).then(() => { +// ElMessage({ +// message: "Save success", +// type: "success", +// showClose: true, +// }); +// }); +// }; + +const editTable = () => { + tableDialog.value = true +} + +const closeTable = () => { + tableDialog.value = false +} + +const saveTable = () => { + datasourceApi.saveTable(currentTable.value).then(() => { + closeTable() ElMessage({ - message: "Save success", + message: "Edit Success", type: "success", showClose: true, - }); - }); -}; + }) + }) +} + +const editField = (row: any) => { + currentField.value = row + fieldDialog.value = true +} + +const changeStatus = (row: any) => { + currentField.value = row + saveField() +} + +const closeField = () => { + fieldDialog.value = false +} + +const saveField = () => { + datasourceApi.saveField(currentField.value).then(() => { + closeField() + ElMessage({ + message: "Edit Success", + type: "success", + showClose: true, + }) + }) +} const clickTable = (table: any) => { currentTable.value = table; @@ -200,4 +292,13 @@ onMounted(() => { } } } + +.field-comment{ + display: flex; + align-items: center; + + .action-btn{ + margin-left: 10px; + } +}