完善细节
This commit is contained in:
@@ -20,7 +20,7 @@ def get_cube_report_settings() -> CubeReportSettings:
|
||||
"DIFY_DATABASE_ASSISTANT_API_BASE", "https://chat.bbitcn.net/v1"
|
||||
).rstrip("/"),
|
||||
dify_api_key=os.getenv(
|
||||
"DIFY_DATABASE_ASSISTANT_API_KEY", "app-uibWo8ZEpqHCsWXREPTCBDH6"
|
||||
"DIFY_DATABASE_ASSISTANT_API_KEY", "app-Ojd3zT2wBsO2Bop575ZiHQOD"
|
||||
),
|
||||
cube_api_base=os.getenv(
|
||||
"CUBE_API_BASE_URL", "http://10.10.12.101:4001/cubejs-api/v1"
|
||||
|
||||
@@ -138,6 +138,32 @@ function getFetchConfig() {
|
||||
};
|
||||
}
|
||||
|
||||
async function authorizedFetch(path: string, init: RequestInit) {
|
||||
const request = () => {
|
||||
const { authorization, baseURL } = getFetchConfig();
|
||||
const headers = new Headers(init.headers);
|
||||
if (authorization) {
|
||||
headers.set('Authorization', authorization);
|
||||
} else {
|
||||
headers.delete('Authorization');
|
||||
}
|
||||
return fetch(`${baseURL}${path}`, { ...init, headers });
|
||||
};
|
||||
|
||||
let response = await request();
|
||||
if (response.status !== 401) return response;
|
||||
|
||||
try {
|
||||
// 标准请求客户端会使用项目现有的 refresh token 机制更新令牌。
|
||||
await getCubeReportScope();
|
||||
} catch {
|
||||
return response;
|
||||
}
|
||||
await response.body?.cancel();
|
||||
response = await request();
|
||||
return response;
|
||||
}
|
||||
|
||||
async function responseError(response: Response) {
|
||||
const text = await response.text();
|
||||
try {
|
||||
@@ -272,12 +298,10 @@ export async function stopCubeReportTask(taskId: string) {
|
||||
}
|
||||
|
||||
export async function uploadCubeReportFile(file: File) {
|
||||
const { authorization, baseURL } = getFetchConfig();
|
||||
const form = new FormData();
|
||||
form.append('file', file);
|
||||
const response = await fetch(`${baseURL}/llm/cube-report/files/upload`, {
|
||||
const response = await authorizedFetch('/llm/cube-report/files/upload', {
|
||||
method: 'POST',
|
||||
headers: { Authorization: authorization },
|
||||
body: form,
|
||||
});
|
||||
if (!response.ok) throw new Error(await responseError(response));
|
||||
@@ -291,14 +315,13 @@ export async function downloadCubeReportFile(
|
||||
conversationId: string,
|
||||
file: CubeReportFile,
|
||||
) {
|
||||
const { authorization, baseURL } = getFetchConfig();
|
||||
const params = new URLSearchParams({
|
||||
conversationId,
|
||||
asAttachment: 'true',
|
||||
});
|
||||
const response = await fetch(
|
||||
`${baseURL}/llm/cube-report/files/${file.id}/preview?${params}`,
|
||||
{ headers: { Authorization: authorization } },
|
||||
const response = await authorizedFetch(
|
||||
`/llm/cube-report/files/${file.id}/preview?${params}`,
|
||||
{},
|
||||
);
|
||||
if (!response.ok) throw new Error(await responseError(response));
|
||||
const blob = await response.blob();
|
||||
@@ -314,12 +337,10 @@ export async function streamCubeReportMessage(
|
||||
payload: SendCubeReportMessage,
|
||||
onEvent: (event: CubeReportStreamEvent) => void,
|
||||
) {
|
||||
const { authorization, baseURL } = getFetchConfig();
|
||||
const response = await fetch(`${baseURL}/llm/cube-report/messages/stream`, {
|
||||
const response = await authorizedFetch('/llm/cube-report/messages/stream', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Accept: 'text/event-stream',
|
||||
Authorization: authorization,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
|
||||
@@ -380,6 +380,7 @@ async function sendMessage() {
|
||||
|
||||
let completedConversationId = currentSessionId.value;
|
||||
let completedWithData = false;
|
||||
try {
|
||||
try {
|
||||
await api.streamCubeReportMessage(
|
||||
{
|
||||
@@ -424,26 +425,6 @@ async function sendMessage() {
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (!assistantMessage.content) {
|
||||
assistantMessage.content = stopRequested.value
|
||||
? '响应已停止。'
|
||||
: '查询已完成。';
|
||||
}
|
||||
if (completedConversationId) {
|
||||
currentSessionId.value = completedConversationId;
|
||||
const detail = await api.getCubeReportSession(completedConversationId);
|
||||
currentSession.value = detail.session;
|
||||
messages.value = detail.messages;
|
||||
if (currentReportId.value) {
|
||||
currentReport.value = await api.getCubeReport(currentReportId.value);
|
||||
}
|
||||
await reloadNavigation();
|
||||
if (completedWithData || detail.session.hasData) {
|
||||
activeView.value = 'split';
|
||||
await loadData(1);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
const text =
|
||||
error instanceof Error ? error.message : '请求失败,请稍后重试';
|
||||
@@ -456,6 +437,34 @@ async function sendMessage() {
|
||||
pendingFiles.value = sentFiles;
|
||||
message.error(text);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!assistantMessage.content) {
|
||||
assistantMessage.content = stopRequested.value
|
||||
? '响应已停止。'
|
||||
: '查询已完成。';
|
||||
}
|
||||
if (completedConversationId) {
|
||||
try {
|
||||
currentSessionId.value = completedConversationId;
|
||||
const detail = await api.getCubeReportSession(completedConversationId);
|
||||
currentSession.value = detail.session;
|
||||
messages.value = detail.messages;
|
||||
if (currentReportId.value) {
|
||||
currentReport.value = await api.getCubeReport(currentReportId.value);
|
||||
}
|
||||
await reloadNavigation();
|
||||
if (completedWithData || detail.session.hasData) {
|
||||
activeView.value = 'split';
|
||||
await loadData(1);
|
||||
}
|
||||
} catch (error) {
|
||||
const text =
|
||||
error instanceof Error ? error.message : '会话和数据刷新失败';
|
||||
message.warning(`回复已完成,但数据刷新失败:${text}`);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
sending.value = false;
|
||||
stopping.value = false;
|
||||
@@ -465,6 +474,12 @@ async function sendMessage() {
|
||||
}
|
||||
}
|
||||
|
||||
function sendSuggestedQuestion(question: string) {
|
||||
if (sending.value) return;
|
||||
inputMessage.value = question;
|
||||
void sendMessage();
|
||||
}
|
||||
|
||||
async function stopResponse() {
|
||||
if (!currentTaskId.value || stopping.value) return;
|
||||
stopping.value = true;
|
||||
@@ -1183,17 +1198,14 @@ onBeforeUnmount(() => {
|
||||
v-for="(question, index) in suggestedQuestions"
|
||||
:key="question"
|
||||
type="button"
|
||||
@click="inputMessage = question"
|
||||
:disabled="sending"
|
||||
@click="sendSuggestedQuestion(question)"
|
||||
>
|
||||
<IconifyIcon
|
||||
:icon="suggestionIcons[index % suggestionIcons.length]!"
|
||||
/>
|
||||
<span>{{ question }}</span>
|
||||
</button>
|
||||
<button type="button" @click="fileInput?.click()">
|
||||
<IconifyIcon icon="lucide:file-up" />
|
||||
<span>上传 Excel 辅助分析</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Spin>
|
||||
|
||||
+2716
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user