Skip to content

Commit 86abe25

Browse files
committed
feat: export
1 parent 8b20110 commit 86abe25

File tree

5 files changed

+30
-22
lines changed

5 files changed

+30
-22
lines changed

backend/apps/chat/api/chat.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import datetime
2+
import hashlib
3+
import io
24
import traceback
5+
import uuid
36

47
import numpy as np
58
import pandas as pd
@@ -12,6 +15,7 @@
1215
from apps.chat.task.llm import LLMService
1316
from common.core.config import settings
1417
from common.core.deps import CurrentAssistant, SessionDep, CurrentUser
18+
from starlette.responses import FileResponse
1519

1620
router = APIRouter(tags=["Data Q&A"], prefix="/chat")
1721

@@ -202,12 +206,12 @@ async def export_excel(excel_data: ExcelData):
202206
_fields_list.append(field.name)
203207
df = pd.DataFrame(np.array(data), columns=_fields_list)
204208

205-
file_name = f"{excel_data.name}-{datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.xlsx"
209+
file_name = f"{excel_data.name}-{datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}_{hashlib.sha256(uuid.uuid4().bytes).hexdigest()[:10]}.xlsx"
206210

207211
file_path = f'{(settings.EXCEL_PATH if settings.EXCEL_PATH[-1] == "/" else (settings.EXCEL_PATH + "/"))}{file_name}'
208212

209-
file_download_path = f'{(settings.SERVER_EXCEL_HOST if settings.SERVER_EXCEL_HOST[-1] == "/" else (settings.SERVER_EXCEL_HOST + "/"))}{file_name}'
213+
buffer = io.BytesIO()
214+
df.to_excel(buffer, index=False)
215+
buffer.seek(0)
210216

211-
df.to_excel(file_path, index=False)
212-
213-
return file_download_path
217+
return StreamingResponse(io.BytesIO(buffer.getvalue()))

backend/apps/datasource/api/datasource.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from fastapi import APIRouter, File, UploadFile, HTTPException
99

1010
from apps.db.engine import create_table, get_data_engine, insert_data
11+
from common.core.config import settings
1112
from common.core.deps import SessionDep, CurrentUser, Trans
1213
from common.utils.utils import SQLBotLogUtil
1314
from ..crud.datasource import get_datasource_list, check_status, create_ds, update_ds, delete_ds, getTables, getFields, \
@@ -17,7 +18,7 @@
1718
from ..models.datasource import CoreDatasource, CreateDatasource, TableObj, CoreTable, CoreField
1819

1920
router = APIRouter(tags=["datasource"], prefix="/datasource")
20-
path = "/opt/sqlbot/data/excel"
21+
path = settings.EXCEL_PATH
2122

2223

2324
@router.get("/ws/{oid}", include_in_schema=False)

backend/common/core/config.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,8 @@ def SQLALCHEMY_DATABASE_URI(self) -> PostgresDsn | str:
7979
)
8080

8181
MCP_IMAGE_PATH: str = '/opt/sqlbot/images'
82-
EXCEL_PATH: str
82+
EXCEL_PATH: str = '/opt/sqlbot/data/excel'
8383
MCP_IMAGE_HOST: str = 'http://localhost:3000'
8484
SERVER_IMAGE_HOST: str
85-
SERVER_EXCEL_HOST: str
8685

8786
settings = Settings() # type: ignore

backend/main.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
1-
from fastapi.concurrency import asynccontextmanager
1+
import sqlbot_xpack
2+
from alembic.config import Config
23
from fastapi import FastAPI
4+
from fastapi.concurrency import asynccontextmanager
35
from fastapi.routing import APIRoute
4-
from starlette.middleware.cors import CORSMiddleware
6+
from fastapi.staticfiles import StaticFiles
7+
from fastapi_mcp import FastApiMCP
58
from starlette.exceptions import HTTPException as StarletteHTTPException
9+
from starlette.middleware.cors import CORSMiddleware
610

11+
from alembic import command
12+
from apps.api import api_router
713
from apps.system.crud.assistant import init_dynamic_cors
814
from apps.system.middleware.auth import TokenMiddleware
915
from common.core.config import settings
1016
from common.core.response_middleware import ResponseMiddleware, exception_handler
11-
from alembic.config import Config
12-
from alembic import command
13-
from fastapi_mcp import FastApiMCP
14-
from fastapi.staticfiles import StaticFiles
15-
import sqlbot_xpack
16-
from common.utils.utils import SQLBotLogUtil
1717
from common.core.sqlbot_cache import init_sqlbot_cache
18-
from apps.api import api_router
18+
from common.utils.utils import SQLBotLogUtil
19+
1920

2021
def run_migrations():
2122
alembic_cfg = Config("alembic.ini")
@@ -32,6 +33,7 @@ async def lifespan(app: FastAPI):
3233
yield
3334
SQLBotLogUtil.info("SQLBot 应用关闭")
3435

36+
3537
def custom_generate_unique_id(route: APIRoute) -> str:
3638
tag = route.tags[0] if route.tags and len(route.tags) > 0 else ""
3739
return f"{tag}-{route.name}"
@@ -44,9 +46,6 @@ def custom_generate_unique_id(route: APIRoute) -> str:
4446
lifespan=lifespan
4547
)
4648

47-
app.mount("/excel", StaticFiles(directory=settings.EXCEL_PATH), name="excel")
48-
49-
5049
mcp_app = FastAPI()
5150
# mcp server, images path
5251
mcp_app.mount("/images", StaticFiles(directory=settings.MCP_IMAGE_PATH), name="images")

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,13 @@ function exportToExcel() {
232232
chatApi
233233
.export2Excel({ ...chartRef.value?.getExcelData(), name: chartObject.value.title })
234234
.then((res) => {
235-
console.log('download_path: ' + res)
236-
//todo download
235+
const blob = new Blob([res.data])
236+
const link = document.createElement('a')
237+
link.href = URL.createObjectURL(blob)
238+
link.download = `${chartObject.value.title ?? 'Excel'}.xlsx`
239+
document.body.appendChild(link)
240+
link.click()
241+
document.body.removeChild(link)
237242
})
238243
exportRef.value?.hide()
239244
}

0 commit comments

Comments
 (0)