dify修正

This commit is contained in:
2025-11-17 18:34:37 +08:00
parent ba0f14489e
commit 2ce3684711
7 changed files with 127 additions and 19 deletions

View File

@@ -0,0 +1,9 @@
# 1.工作流修改
## 动态知识库检索工作流
修改dataset的apikey
## 思政小帮手对话流
修改“动态知识库检索”的入参
# 2. 后端修改
修改yaml的配置内容

View File

@@ -111,6 +111,7 @@ school-news:
- "/public/**" - "/public/**"
- "/static/**" - "/static/**"
- "/file/download/**" - "/file/download/**"
- "/ai/chat/stream/**"
crawler: crawler:
@@ -158,6 +159,10 @@ crontab:
type: Boolean type: Boolean
value: true value: true
# dify
dify:
knowledgeApiKey: dataset-nupqKP4LONpzdXmGthIrbjeJ
# 文件存储配置 # 文件存储配置
file: file:
storage: storage:

View File

@@ -514,6 +514,13 @@ public class DifyApiClient {
} }
} }
} }
// 流正常读取完毕,如果没有收到 [DONE] 标记,也当作完成
logger.info("SSE流读取完毕");
callback.onComplete();
} catch (java.io.EOFException e) {
// EOFException 通常表示流正常结束Dify可能没有发送[DONE]标记)
logger.info("SSE流已结束EOF");
callback.onComplete();
} catch (Exception e) { } catch (Exception e) {
logger.error("流式响应处理异常", e); logger.error("流式响应处理异常", e);
callback.onError(e); callback.onError(e);

View File

@@ -31,9 +31,9 @@ public class DifyConfig {
* Dify API密钥默认密钥可被智能体的密钥覆盖 * Dify API密钥默认密钥可被智能体的密钥覆盖
*/ */
// private String apiKey="app-PTHzp2DsLPyiUrDYTXBGxL1f"; // private String apiKey="app-PTHzp2DsLPyiUrDYTXBGxL1f";
private String apiKey="app-fwOqGFLTsZtekCQYlOmj9f8x"; private String apiKey="app-6VXXDHRC8fiTijeRfnwzOyGn";
private String knowledgeApiKey="dataset-HeDK9gHBqPnI4rBZ2q2Hm7rV"; private String knowledgeApiKey="dataset-nupqKP4LONpzdXmGthIrbjeJ";
/** /**
* 请求超时时间(秒) * 请求超时时间(秒)

View File

@@ -148,7 +148,7 @@
complete_time = #{completeTime}, complete_time = #{completeTime},
</if> </if>
<if test="lastLearnTime != null"> <if test="lastLearnTime != null">
last_learn_time = #{lastLearnTime}, last_learn_time = #{updateTime},
</if> </if>
<if test="updater != null"> <if test="updater != null">
updater = #{updater}, updater = #{updater},
@@ -298,8 +298,8 @@
) current_dept ON user_dept.dept_path LIKE CONCAT(current_dept.dept_path, '%') ) current_dept ON user_dept.dept_path LIKE CONCAT(current_dept.dept_path, '%')
</if> </if>
WHERE lr.deleted = 0 WHERE lr.deleted = 0
AND lr.last_learn_time >= DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY) AND lr.update_time &gt;= DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY)
AND lr.last_learn_time &lt; DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY), INTERVAL 7 DAY) AND lr.update_time &lt; DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY), INTERVAL 7 DAY)
GROUP BY lr.resource_type GROUP BY lr.resource_type
ORDER BY totalDuration DESC ORDER BY totalDuration DESC
</select> </select>
@@ -326,8 +326,8 @@
) current_dept ON user_dept.dept_path LIKE CONCAT(current_dept.dept_path, '%') ) current_dept ON user_dept.dept_path LIKE CONCAT(current_dept.dept_path, '%')
</if> </if>
WHERE lr.deleted = 0 WHERE lr.deleted = 0
AND lr.last_learn_time >= DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY) AND lr.update_time >= DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY)
AND lr.last_learn_time &lt; DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY), INTERVAL 7 DAY) AND lr.update_time &lt; DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY), INTERVAL 7 DAY)
GROUP BY lr.user_id, u.username GROUP BY lr.user_id, u.username
ORDER BY totalDuration DESC ORDER BY totalDuration DESC
LIMIT 10 LIMIT 10
@@ -357,8 +357,8 @@
</if> </if>
WHERE lr.deleted = 0 WHERE lr.deleted = 0
AND lr.resource_type = 2 AND lr.resource_type = 2
AND lr.last_learn_time >= DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY) AND lr.update_time >= DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY)
AND lr.last_learn_time &lt; DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY), INTERVAL 7 DAY) AND lr.update_time &lt; DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY), INTERVAL 7 DAY)
GROUP BY lr.resource_id, c.name GROUP BY lr.resource_id, c.name
ORDER BY learnerCount DESC, totalDuration DESC ORDER BY learnerCount DESC, totalDuration DESC
LIMIT 10 LIMIT 10
@@ -388,8 +388,8 @@
</if> </if>
WHERE lr.deleted = 0 WHERE lr.deleted = 0
AND lr.resource_type = 1 AND lr.resource_type = 1
AND lr.last_learn_time >= DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY) AND lr.update_time >= DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY)
AND lr.last_learn_time &lt; DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY), INTERVAL 7 DAY) AND lr.update_time &lt; DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY), INTERVAL 7 DAY)
GROUP BY lr.resource_id, r.title GROUP BY lr.resource_id, r.title
ORDER BY learnerCount DESC, totalDuration DESC ORDER BY learnerCount DESC, totalDuration DESC
LIMIT 10 LIMIT 10
@@ -419,7 +419,7 @@
LEFT JOIN tb_learning_record lr ON tu.user_id = lr.user_id AND tu.task_id = lr.task_id AND lr.deleted = 0 LEFT JOIN tb_learning_record lr ON tu.user_id = lr.user_id AND tu.task_id = lr.task_id AND lr.deleted = 0
WHERE tu.deleted = 0 WHERE tu.deleted = 0
AND tu.status = 2 AND tu.status = 2
AND tu.complete_time >= DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY) AND tu.complete_time &gt;= DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY)
AND tu.complete_time &lt; DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY), INTERVAL 7 DAY) AND tu.complete_time &lt; DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAYOFWEEK(CURDATE())-1 DAY), INTERVAL 7 DAY)
GROUP BY tu.user_id, u.username GROUP BY tu.user_id, u.username
ORDER BY completedTaskCount DESC, totalDuration DESC ORDER BY completedTaskCount DESC, totalDuration DESC

View File

@@ -127,7 +127,35 @@ export const chatApi = {
// 监听错误事件 // 监听错误事件
eventSource.addEventListener('error', (event: any) => { eventSource.addEventListener('error', (event: any) => {
const error = new Error(event.data || '对话失败'); // 如果 data 为空说明是正常的流结束信号有些工作流不发送end事件
if (!event.data || event.data.trim() === '') {
console.log('[SSE流结束] 收到空error事件当作正常结束处理');
// 触发结束回调(如果有的话)
callback?.onMessageEnd?.({
conversationId: request.conversationId,
messageId: '',
answer: fullMessage
} as any);
eventSource.close();
// 正常结束
resolve({
code: 200,
success: true,
login: true,
auth: true,
data: {
conversationId: request.conversationId,
answer: fullMessage
} as any,
message: '对话已结束'
});
return;
}
const error = new Error(event.data);
callback?.onError?.(error); callback?.onError?.(error);
eventSource.close(); eventSource.close();
reject(error); reject(error);
@@ -358,7 +386,34 @@ export const chatApi = {
// 监听错误事件 // 监听错误事件
eventSource.addEventListener('error', (event: any) => { eventSource.addEventListener('error', (event: any) => {
const error = new Error(event.data || '重新生成失败'); // 如果 data 为空说明是正常的流结束信号有些工作流不发送end事件
if (!event.data || event.data.trim() === '') {
console.log('[SSE流结束-重新生成] 收到空error事件当作正常结束处理');
// 触发结束回调(如果有的话)
callback?.onMessageEnd?.({
messageId: messageId,
answer: fullMessage
} as any);
eventSource.close();
// 正常结束
resolve({
code: 200,
success: true,
login: true,
auth: true,
data: {
messageId: messageId,
answer: fullMessage
} as any,
message: '重新生成已结束'
});
return;
}
const error = new Error(event.data);
callback?.onError?.(error); callback?.onError?.(error);
eventSource.close(); eventSource.close();
reject(error); reject(error);

View File

@@ -180,7 +180,14 @@ function initDurationChart(data: any[]) {
const duration = params.value; const duration = params.value;
const hours = Math.floor(duration / 3600); const hours = Math.floor(duration / 3600);
const minutes = Math.floor((duration % 3600) / 60); const minutes = Math.floor((duration % 3600) / 60);
return `${params.name}<br/>学习时长: ${hours}小时${minutes}分钟<br/>学习人数: ${params.data.userCount}`; const secs = duration % 60;
let timeStr = '';
if (hours > 0) timeStr += `${hours}小时`;
if (minutes > 0) timeStr += `${minutes}分钟`;
if (secs > 0 || timeStr === '') timeStr += `${secs}`;
return `${params.name}<br/>学习时长: ${timeStr}<br/>学习人数: ${params.data.userCount}`;
} }
}, },
legend: { legend: {
@@ -204,7 +211,18 @@ function initDurationChart(data: any[]) {
const duration = params.value; const duration = params.value;
const hours = Math.floor(duration / 3600); const hours = Math.floor(duration / 3600);
const minutes = Math.floor((duration % 3600) / 60); const minutes = Math.floor((duration % 3600) / 60);
return `${params.name}\n${hours}h${minutes}m`; const secs = duration % 60;
let timeStr = '';
if (hours > 0) {
timeStr = `${hours}h${minutes}m`;
} else if (minutes > 0) {
timeStr = `${minutes}m${secs}s`;
} else {
timeStr = `${secs}s`;
}
return `${params.name}\n${timeStr}`;
} }
}, },
emphasis: { emphasis: {
@@ -233,12 +251,26 @@ function initDurationChart(data: any[]) {
// 格式化时长 // 格式化时长
function formatDuration(seconds: number): string { function formatDuration(seconds: number): string {
if (!seconds || seconds === 0) {
return '0秒';
}
const hours = Math.floor(seconds / 3600); const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60); const minutes = Math.floor((seconds % 3600) / 60);
const secs = seconds % 60;
let result = '';
if (hours > 0) { if (hours > 0) {
return `${hours}小时${minutes}分钟`; result += `${hours}小时`;
} }
return `${minutes}分钟`; if (minutes > 0) {
result += `${minutes}分钟`;
}
if (secs > 0 || result === '') {
result += `${secs}`;
}
return result;
} }
// 获取排名样式 // 获取排名样式
@@ -294,7 +326,7 @@ function getRankClass(index: number): string {
&:hover { &:hover {
background: #e8edf3; background: #e8edf3;
transform: translateX(5px); // transform: translateX(5px);
} }
.rank { .rank {