|
@@ -1,6 +1,7 @@
|
|
|
import LoginModal from "@/components/LoginModal";
|
|
|
import MarkdownIt from "markdown-it";
|
|
|
-import { pcInnerAi } from "@/api/api";
|
|
|
+import { pcInnerAi,getMinioURl } from "@/api/api";
|
|
|
+import axios from 'axios';
|
|
|
const md = new MarkdownIt();
|
|
|
|
|
|
export default {
|
|
@@ -28,6 +29,8 @@ export default {
|
|
|
tweaks:{},
|
|
|
showLoginModal: false,
|
|
|
isLoggedIn: false, // 添加登录状态标志
|
|
|
+ idArray: [],
|
|
|
+ minioUrls: [], // 新增:用于存储 Minio URL
|
|
|
};
|
|
|
},
|
|
|
created() {
|
|
@@ -51,6 +54,17 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
+ handleLinkClick(event) {
|
|
|
+ if (event.target.tagName === 'A') {
|
|
|
+ localStorage.setItem('href',event.target.href)
|
|
|
+ let _this = this;
|
|
|
+ let a = document.createElement("a");
|
|
|
+ a.href = "#/preview"; // 使用 hash
|
|
|
+ a.target = "_blank";
|
|
|
+ a.click();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
handleLoginSuccess() {
|
|
|
this.showLoginModal = false;
|
|
|
this.isLoggedIn = true;
|
|
@@ -164,14 +178,14 @@ export default {
|
|
|
tweaks:this.tweaks /* {
|
|
|
"ChatInput-U82Vu": {},
|
|
|
"Prompt-b8Z1E": {},
|
|
|
- "ChatOutput-Yf4KV": {},
|
|
|
"OllamaModel-z9SVx": {},
|
|
|
"Milvus-l0vvr": {},
|
|
|
"OllamaEmbeddings-4Ml5q": {},
|
|
|
- "APIRequest-lH4wg": {},
|
|
|
"ParseData-LM8yW": {},
|
|
|
"ParseData-jVoZg": {},
|
|
|
- "Memory-3IxGM": {}
|
|
|
+ "APIRequest-OnZHl": {},
|
|
|
+ "ParseData-fH1vY": {},
|
|
|
+ "ChatOutput-ybzb9": {}
|
|
|
} */,
|
|
|
}),
|
|
|
});
|
|
@@ -186,7 +200,22 @@ export default {
|
|
|
const result = await response.json();
|
|
|
// 等待思考动画完成
|
|
|
await thinkingPromise;
|
|
|
-
|
|
|
+ // 提取 additional_input 数据
|
|
|
+ const additionalInput = result.outputs[0].outputs[0].results.message.data.additional_input;
|
|
|
+
|
|
|
+ // 处理字符串,提取 ID 值
|
|
|
+ this.idArray = additionalInput.split('\n') // 按换行符分割
|
|
|
+ .map(line => line.trim()) // 去除每行首尾空白
|
|
|
+ .filter(line => line.startsWith('ID:')) // 只保留以 'ID:' 开头的行
|
|
|
+ .map(line => line.substring(3).trim()); // 提取 'ID:' 后面的内容并去除空白
|
|
|
+
|
|
|
+ // 创建符合要求格式的对象
|
|
|
+ const idObject = { ids: this.idArray };
|
|
|
+
|
|
|
+ console.log("ID Object:", idObject);
|
|
|
+
|
|
|
+ // 调用方法来获取 Minio URL,传递新的 idObject
|
|
|
+ await this.getMinioUrls(idObject);
|
|
|
this.handleResponse(result, botMessage);
|
|
|
} catch (error) {
|
|
|
console.error("Error sending message:", error);
|
|
@@ -196,6 +225,37 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
+ async getMinioUrls(idObject) {
|
|
|
+ this.minioUrls = []; // 清空之前的 URL
|
|
|
+
|
|
|
+ try {
|
|
|
+ console.log("Sending to backend:", JSON.stringify(idObject));
|
|
|
+
|
|
|
+ const response = await axios.post('http://58.246.234.210:8084/milvus/getMinioURl', idObject, {
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (response.status === 200 && response.data) {
|
|
|
+ this.minioUrls = response.data.data; // 假设返回的是 URL 数组
|
|
|
+ console.log("Received Minio URLs:", this.minioUrls);
|
|
|
+ } else {
|
|
|
+ console.error('Failed to get Minio URLs');
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Error fetching Minio URLs:', error);
|
|
|
+ if (error.response) {
|
|
|
+ console.error('Response data:', error.response.data);
|
|
|
+ console.error('Response status:', error.response.status);
|
|
|
+ console.error('Response headers:', error.response.headers);
|
|
|
+ } else if (error.request) {
|
|
|
+ console.error('No response received:', error.request);
|
|
|
+ } else {
|
|
|
+ console.error('Error message:', error.message);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
async simulateThinking(message) {
|
|
|
this.isThinking = true;
|
|
|
const thinkingTime = Math.random() * 1000 + 500; // 思考时间为 0.5-1.5 秒
|
|
@@ -222,22 +282,35 @@ export default {
|
|
|
async handleResponse(value, existingMessage) {
|
|
|
const data = value.outputs[0].outputs[0].results.message;
|
|
|
|
|
|
- // 更新现有的消息对象
|
|
|
existingMessage.messageType = data.text_key;
|
|
|
existingMessage.time = data.timestamp;
|
|
|
-
|
|
|
- // 移除思考动画
|
|
|
existingMessage.message = '';
|
|
|
|
|
|
- // 开始打字效果
|
|
|
- await this.typeMessage(existingMessage, data.text);
|
|
|
+ let mainText = data.text;
|
|
|
+ let sourceText = '';
|
|
|
+
|
|
|
+ if (this.$route.name !== 'ai' && this.minioUrls && this.minioUrls.length > 0) {
|
|
|
+ sourceText = "\n\n<div class='source-section'><h3>相关资料来源:</h3><ol>";
|
|
|
+ this.minioUrls.forEach((url, index) => {
|
|
|
+ sourceText += `<li><a href="${url.url}" target="_blank" class="source-link">${url.object_name}</a></li>`;
|
|
|
+ });
|
|
|
+ sourceText += "</ol></div>";
|
|
|
+ }
|
|
|
+
|
|
|
+ // 先进行主要内容的打字效果
|
|
|
+ await this.typeMessage(existingMessage, mainText);
|
|
|
+
|
|
|
+ // 直接添加资料来源部分
|
|
|
+ if (sourceText) {
|
|
|
+ existingMessage.message += sourceText;
|
|
|
+ existingMessage.html = this.renderMarkdown(existingMessage.message);
|
|
|
+ }
|
|
|
},
|
|
|
-
|
|
|
+
|
|
|
typeMessage(message, fullText) {
|
|
|
return new Promise(resolve => {
|
|
|
- const delay = 30; // 每个字符之间的延迟时间(毫秒)
|
|
|
+ const delay = 30;
|
|
|
let i = 0;
|
|
|
-
|
|
|
const typeChar = () => {
|
|
|
if (i < fullText.length) {
|
|
|
message.message += fullText[i];
|
|
@@ -245,6 +318,7 @@ export default {
|
|
|
setTimeout(typeChar, delay);
|
|
|
} else {
|
|
|
message.done = true;
|
|
|
+ message.html = this.renderMarkdown(message.message);
|
|
|
resolve();
|
|
|
}
|
|
|
};
|
|
@@ -253,7 +327,37 @@ export default {
|
|
|
});
|
|
|
},
|
|
|
renderMarkdown(rawMarkdown) {
|
|
|
- return md.render(rawMarkdown);
|
|
|
+ const md = new MarkdownIt({
|
|
|
+ html: true,
|
|
|
+ breaks: true,
|
|
|
+ linkify: true
|
|
|
+ });
|
|
|
+
|
|
|
+ // 自定义链接渲染规则
|
|
|
+ md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
|
|
|
+ const token = tokens[idx];
|
|
|
+ const hrefIndex = token.attrIndex('href');
|
|
|
+ const href = token.attrs[hrefIndex][1];
|
|
|
+ return `<span class="custom-link" data-href="${href}">`;
|
|
|
+ };
|
|
|
+
|
|
|
+ md.renderer.rules.link_close = () => '</span>';
|
|
|
+
|
|
|
+ const renderedHtml = md.render(rawMarkdown);
|
|
|
+
|
|
|
+ // 使用 setTimeout 来确保 DOM 更新后再添加事件监听器
|
|
|
+ setTimeout(() => {
|
|
|
+ const links = document.querySelectorAll('.custom-link');
|
|
|
+ links.forEach(link => {
|
|
|
+ link.addEventListener('click', (e) => {
|
|
|
+ e.preventDefault();
|
|
|
+ const href = link.getAttribute('data-href');
|
|
|
+ window.open(href, '_blank');
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }, 0);
|
|
|
+
|
|
|
+ return renderedHtml;
|
|
|
},
|
|
|
handleKeydown(event) {
|
|
|
// Check if 'Enter' is pressed without the 'Alt' key
|