添加论文搜索功能
This commit is contained in:
@@ -0,0 +1 @@
|
||||
<svg fill="#ffffff" viewBox="-1.92 -1.92 27.84 27.84" role="img" xmlns="http://www.w3.org/2000/svg" stroke="#ffffff" stroke-width="0.00024000000000000003" transform="rotate(0)"><g id="SVGRepo_bgCarrier" stroke-width="0" transform="translate(0,0), scale(1)"><rect x="-1.92" y="-1.92" width="27.84" height="27.84" rx="6.96" fill="#000000" strokewidth="0"></rect></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round" stroke="#030303" stroke-width="0.288"><title>Zhihu icon</title><path d="M5.721 0C2.251 0 0 2.25 0 5.719V18.28C0 21.751 2.252 24 5.721 24h12.56C21.751 24 24 21.75 24 18.281V5.72C24 2.249 21.75 0 18.281 0zm1.964 4.078c-.271.73-.5 1.434-.68 2.11h4.587c.545-.006.445 1.168.445 1.171H9.384a58.104 58.104 0 01-.112 3.797h2.712c.388.023.393 1.251.393 1.266H9.183a9.223 9.223 0 01-.408 2.102l.757-.604c.452.456 1.512 1.712 1.906 2.177.473.681.063 2.081.063 2.081l-2.794-3.382c-.653 2.518-1.845 3.607-1.845 3.607-.523.468-1.58.82-2.64.516 2.218-1.73 3.44-3.917 3.667-6.497H4.491c0-.015.197-1.243.806-1.266h2.71c.024-.32.086-3.254.086-3.797H6.598c-.136.406-.158.447-.268.753-.594 1.095-1.603 1.122-1.907 1.155.906-1.821 1.416-3.6 1.591-4.064.425-1.124 1.671-1.125 1.671-1.125zM13.078 6h6.377v11.33h-2.573l-2.184 1.373-.401-1.373h-1.219zm1.313 1.219v8.86h.623l.263.937 1.455-.938h1.456v-8.86z"></path></g><g id="SVGRepo_iconCarrier"><title>Zhihu icon</title><path d="M5.721 0C2.251 0 0 2.25 0 5.719V18.28C0 21.751 2.252 24 5.721 24h12.56C21.751 24 24 21.75 24 18.281V5.72C24 2.249 21.75 0 18.281 0zm1.964 4.078c-.271.73-.5 1.434-.68 2.11h4.587c.545-.006.445 1.168.445 1.171H9.384a58.104 58.104 0 01-.112 3.797h2.712c.388.023.393 1.251.393 1.266H9.183a9.223 9.223 0 01-.408 2.102l.757-.604c.452.456 1.512 1.712 1.906 2.177.473.681.063 2.081.063 2.081l-2.794-3.382c-.653 2.518-1.845 3.607-1.845 3.607-.523.468-1.58.82-2.64.516 2.218-1.73 3.44-3.917 3.667-6.497H4.491c0-.015.197-1.243.806-1.266h2.71c.024-.32.086-3.254.086-3.797H6.598c-.136.406-.158.447-.268.753-.594 1.095-1.603 1.122-1.907 1.155.906-1.821 1.416-3.6 1.591-4.064.425-1.124 1.671-1.125 1.671-1.125zM13.078 6h6.377v11.33h-2.573l-2.184 1.373-.401-1.373h-1.219zm1.313 1.219v8.86h.623l.263.937 1.455-.938h1.456v-8.86z"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,441 @@
|
||||
// Copyright (c) 2024-present AI-Labs
|
||||
|
||||
// @ ts-nocheck
|
||||
import { EditorEvents } from "@tiptap/core";
|
||||
import { t } from "i18next";
|
||||
|
||||
import { UAIEditorEventListener, UAIEditorOptions } from "../../core/UAIEditor.ts";
|
||||
import { createAvatar } from "../../utils/CreateAvatar.ts";
|
||||
import { Icons } from "../Icons.ts";
|
||||
import { markdownToHtml } from "../../utils/MarkdownUtil.ts";
|
||||
import { AIRequestAction } from "../ai/AIAction.ts";
|
||||
|
||||
import closeIcon from "../../assets/icons/close.svg";
|
||||
import titleIcon from "../../assets/icons/arxiv.svg";
|
||||
import sendIcon from "../../assets/icons/send-message.svg";
|
||||
import { FullScreenModal } from "../modals/FullScreenModal.ts";
|
||||
|
||||
export class ArxivContainer extends HTMLElement implements UAIEditorEventListener {
|
||||
// 容器元素
|
||||
container!: HTMLElement;
|
||||
|
||||
// 标题元素
|
||||
arxivTitle!: HTMLElement;
|
||||
|
||||
// 内容元素
|
||||
content!: HTMLElement;
|
||||
|
||||
// 文本输入框
|
||||
messageTextarea!: HTMLTextAreaElement;
|
||||
imageButton!: HTMLButtonElement;
|
||||
categorySelect!: HTMLSelectElement;
|
||||
subCategorySelect!: HTMLSelectElement;
|
||||
querySelect!: HTMLSelectElement;
|
||||
|
||||
event!: EditorEvents["create"];
|
||||
options!: UAIEditorOptions;
|
||||
|
||||
currentPage = 1;
|
||||
pageSize = 10;
|
||||
|
||||
categories = [
|
||||
{
|
||||
value: 'all', label: 'All Categories', children: [
|
||||
{ value: 'all', label: 'All Categories' }
|
||||
]
|
||||
},
|
||||
{
|
||||
value: 'cs', label: 'Computer Science', children: [
|
||||
{ value: 'cs', label: 'All Computer Science' },
|
||||
{ value: 'cs.AI', label: 'Artificial Intelligence' },
|
||||
{ value: 'cs.AR', label: 'Hardware Architecture' },
|
||||
{ value: 'cs.CC', label: 'Computational Complexity' },
|
||||
]
|
||||
},
|
||||
{
|
||||
value: 'econ', label: 'Economics', children: [
|
||||
{ value: 'econ', label: 'All Economics' },
|
||||
{ value: 'econ.EM', label: 'Econometrics' },
|
||||
{ value: 'econ.GN', label: 'General Economics' },
|
||||
{ value: 'econ.TH', label: 'Theoretical Economics' },
|
||||
]
|
||||
},
|
||||
{
|
||||
value: 'eess', label: 'Electrical Engineering and Systems Science', children: [
|
||||
{ value: 'eess', label: 'Electrical Engineering and Systems Science' }
|
||||
]
|
||||
},
|
||||
{
|
||||
value: 'math', label: 'Mathematics', children: [
|
||||
{ value: 'math', label: 'Mathematics' }
|
||||
]
|
||||
},
|
||||
{
|
||||
value: 'physics', label: 'Physics', children: [
|
||||
{ value: 'physics', label: 'Physics' }
|
||||
]
|
||||
},
|
||||
{
|
||||
value: 'q-bio', label: 'Quantitative Biology', children: [
|
||||
{ value: 'q-bio', label: 'Quantitative Biology' }
|
||||
]
|
||||
},
|
||||
{
|
||||
value: 'q-fin', label: 'Quantitative Finance', children: [
|
||||
{ value: 'q-fin', label: 'Quantitative Finance' }
|
||||
]
|
||||
},
|
||||
{
|
||||
value: 'stat', label: 'Statistics', children: [
|
||||
{ value: 'stat', label: 'Statistics' }
|
||||
]
|
||||
},
|
||||
];
|
||||
queries = [
|
||||
{ value: 'all', label: 'All Papers' },
|
||||
{ value: 'ti', label: 'Titles' },
|
||||
{ value: 'au', label: 'Authors' },
|
||||
{ value: 'abs', label: 'Abstracts' },
|
||||
{ value: 'co', label: 'Comments' },
|
||||
]
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
// 初始化容器
|
||||
this.container = document.createElement("div");
|
||||
this.container.classList.add("uai-pannel-container");
|
||||
this.appendChild(this.container);
|
||||
|
||||
// 初始化标题
|
||||
this.arxivTitle = document.createElement("div");
|
||||
this.arxivTitle.classList.add("uai-pannel-title");
|
||||
this.arxivTitle.innerHTML = `<img src="${titleIcon}" height="24" width="24"/> ${t('tools.arxiv.title')}`
|
||||
this.container.appendChild(this.arxivTitle);
|
||||
// 初始化关闭按钮
|
||||
const dialogClose = document.createElement("div");
|
||||
dialogClose.classList.add("uai-pannel-close");
|
||||
dialogClose.innerHTML = `<img src="${closeIcon}" width="24"/>`;
|
||||
// 点击关闭按钮时关闭容器
|
||||
dialogClose.addEventListener("click", () => {
|
||||
this.style.display = "none";
|
||||
})
|
||||
this.arxivTitle.appendChild(dialogClose);
|
||||
|
||||
const categorySelectDiv = document.createElement('div');
|
||||
categorySelectDiv.classList.add('uai-container-app-models');
|
||||
|
||||
const categorySelectText = document.createElement('div');
|
||||
categorySelectText.innerText = "类别:";
|
||||
categorySelectDiv.appendChild(categorySelectText);
|
||||
|
||||
this.categorySelect = document.createElement('select');
|
||||
this.categorySelect.classList.add('uai-model-select');
|
||||
categorySelectDiv.appendChild(this.categorySelect);
|
||||
this.container.appendChild(categorySelectDiv);
|
||||
|
||||
const subCategorySelectDiv = document.createElement('div');
|
||||
subCategorySelectDiv.classList.add('uai-container-app-models');
|
||||
|
||||
const subCategorySelectText = document.createElement('div');
|
||||
subCategorySelectText.innerText = "子类:";
|
||||
subCategorySelectDiv.appendChild(subCategorySelectText);
|
||||
|
||||
this.subCategorySelect = document.createElement('select');
|
||||
this.subCategorySelect.classList.add('uai-model-select');
|
||||
subCategorySelectDiv.appendChild(this.subCategorySelect);
|
||||
this.container.appendChild(subCategorySelectDiv);
|
||||
|
||||
const querySelectDiv = document.createElement('div');
|
||||
querySelectDiv.classList.add('uai-container-app-models');
|
||||
|
||||
const querySelectText = document.createElement('div');
|
||||
querySelectText.innerText = "查询:";
|
||||
querySelectDiv.appendChild(querySelectText);
|
||||
|
||||
this.querySelect = document.createElement('select');
|
||||
this.querySelect.classList.add('uai-model-select');
|
||||
querySelectDiv.appendChild(this.querySelect);
|
||||
this.container.appendChild(querySelectDiv);
|
||||
|
||||
// 初始化对话内容容器
|
||||
this.content = document.createElement('div');
|
||||
this.content.classList.add('uai-ai-content');
|
||||
this.container.appendChild(this.content);
|
||||
|
||||
// 定义一个监听,当聊天内容有变动时,聊天内容容器滚动到最底部
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
mutations.forEach((mutation) => {
|
||||
if (mutation.type === 'childList' || mutation.type === 'characterData') {
|
||||
this.content.scrollTop = this.content.scrollHeight;
|
||||
}
|
||||
})
|
||||
})
|
||||
// 配置MutationObserver
|
||||
const config = { childList: true, characterData: true };
|
||||
|
||||
// 开始监听div的变化
|
||||
observer.observe(this.content, config);
|
||||
|
||||
// 定义对话输入框组件
|
||||
const divAppInput = document.createElement('div');
|
||||
divAppInput.classList.add('uai-container-app-input');
|
||||
|
||||
const divMessageContainer = document.createElement('div');
|
||||
divMessageContainer.classList.add('uai-message-container');
|
||||
|
||||
this.messageTextarea = document.createElement('textarea');
|
||||
this.messageTextarea.classList.add('uai-message-textarea');
|
||||
this.messageTextarea.rows = 1;
|
||||
this.messageTextarea.placeholder = '请输入内容... Shift+Enter换行;Enter发送';
|
||||
|
||||
// 定义键盘事件,Enter发送数据
|
||||
this.messageTextarea.addEventListener('keydown', (event) => {
|
||||
this.handleKeyDown(event);
|
||||
})
|
||||
// 定义输入事件,输入框自动根据输入内容调整大小
|
||||
this.messageTextarea.addEventListener('input', () => {
|
||||
this.messageTextarea.style.height = 'auto';
|
||||
this.messageTextarea.style.height = this.messageTextarea.scrollHeight + 'px';
|
||||
})
|
||||
divMessageContainer.appendChild(this.messageTextarea);
|
||||
|
||||
// 初始化发送按钮
|
||||
this.imageButton = document.createElement('button');
|
||||
this.imageButton.classList.add('uai-image-button');
|
||||
this.imageButton.innerHTML = `<img src="${sendIcon}" height="24" />`;
|
||||
this.imageButton.addEventListener('click', () => {
|
||||
this.handleSearch(this.messageTextarea.value)
|
||||
})
|
||||
divMessageContainer.appendChild(this.imageButton);
|
||||
|
||||
divAppInput.appendChild(divMessageContainer);
|
||||
this.container.appendChild(divAppInput);
|
||||
}
|
||||
|
||||
onCreate(event: EditorEvents["create"], options: UAIEditorOptions) {
|
||||
this.event = event;
|
||||
this.options = options;
|
||||
|
||||
this.categories.forEach(cat => {
|
||||
const option = document.createElement('option');
|
||||
option.value = cat.value;
|
||||
option.textContent = cat.label;
|
||||
this.categorySelect.appendChild(option);
|
||||
});
|
||||
|
||||
this.categorySelect.addEventListener('change', () => {
|
||||
const subCategories = this.categories.filter(cat => cat.value === this.categorySelect.value).flatMap(cat => cat.children);
|
||||
this.subCategorySelect.innerHTML = '';
|
||||
subCategories.forEach(cat => {
|
||||
const option = document.createElement('option');
|
||||
option.value = cat.value;
|
||||
option.textContent = cat.label;
|
||||
this.subCategorySelect.appendChild(option);
|
||||
});
|
||||
});
|
||||
|
||||
// 触发 categorySelect 的 change 事件,以初始化子类选项
|
||||
this.categorySelect.dispatchEvent(new Event('change'));
|
||||
|
||||
this.queries.forEach(query => {
|
||||
const option = document.createElement('option');
|
||||
option.value = query.value;
|
||||
option.textContent = query.label;
|
||||
this.querySelect.appendChild(option);
|
||||
});
|
||||
}
|
||||
|
||||
onTransaction(event: EditorEvents["transaction"], options: UAIEditorOptions) {
|
||||
|
||||
}
|
||||
|
||||
onEditableChange(editable: boolean) {
|
||||
|
||||
}
|
||||
|
||||
handleKeyDown(event: KeyboardEvent) {
|
||||
// 检查是否按下了 Shift 和 Enter 键
|
||||
if (event.shiftKey && event.key === 'Enter') {
|
||||
// 如果是 Shift + Enter,允许默认行为(通常是换行)
|
||||
return;
|
||||
}
|
||||
// 检查是否按下了 Enter 键
|
||||
if (event.key === 'Enter') {
|
||||
// 阻止默认的换行行为
|
||||
event.preventDefault();
|
||||
// 处理发送消息的逻辑
|
||||
this.handleSearch(this.messageTextarea.value);
|
||||
}
|
||||
}
|
||||
|
||||
handleSearch(message: string) {
|
||||
try {
|
||||
if (message.trim() !== '') {
|
||||
// 创建用户消息容器
|
||||
const userMessageDiv = document.createElement('div');
|
||||
userMessageDiv.classList.add('message');
|
||||
userMessageDiv.classList.add('message-sent');
|
||||
|
||||
// 创建用户发送消息容器
|
||||
const userBubbleDiv = document.createElement('div');
|
||||
userBubbleDiv.classList.add('markdown-body');
|
||||
userBubbleDiv.classList.add('bubble');
|
||||
userBubbleDiv.classList.add('bubble-sent');
|
||||
userBubbleDiv.innerHTML = markdownToHtml(message);
|
||||
userBubbleDiv.setAttribute("InnerContent", message);
|
||||
|
||||
// 创建用户输入的功能按钮
|
||||
const userActionDown = document.createElement(
|
||||
'uai-editor-ai-action-request-action'
|
||||
) as AIRequestAction;
|
||||
userActionDown.classList.add('hidden-content');
|
||||
userActionDown.onCreate(this.event, this.options);
|
||||
userActionDown.bindSourceElement(userBubbleDiv, this.messageTextarea);
|
||||
|
||||
// 创建用户头像容器
|
||||
const userAvatarDiv = createAvatar(Icons.UserAvatar);
|
||||
userAvatarDiv.classList.add('user-avatar');
|
||||
|
||||
// 用户消息容器中,添加功能按钮
|
||||
userMessageDiv.appendChild(userActionDown);
|
||||
// 用户消息容器中,添加用户发送内容
|
||||
userMessageDiv.appendChild(userBubbleDiv);
|
||||
// 用户消息容器中,添加用户头像
|
||||
userMessageDiv.appendChild(userAvatarDiv);
|
||||
|
||||
// 展示用户发送的消息
|
||||
this.content.appendChild(userMessageDiv);
|
||||
|
||||
// 清空消息输入框
|
||||
this.messageTextarea.value = '';
|
||||
this.messageTextarea.style.height = 'auto';
|
||||
this.messageTextarea.style.height = this.messageTextarea.scrollHeight + 'px';
|
||||
this.messageTextarea.focus();
|
||||
|
||||
// 发送消息并等待响应
|
||||
this.fetchArxivData(message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('arXiv API error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
fetchArxivData(message: string) {
|
||||
// 创建模型响应消息容器
|
||||
const botResponseDiv = document.createElement('div');
|
||||
botResponseDiv.classList.add('message');
|
||||
botResponseDiv.classList.add('message-received');
|
||||
|
||||
// 定义模型头像容器
|
||||
const botAvatarDiv = createAvatar(Icons.BotAvatar);
|
||||
botAvatarDiv.classList.add('bot-avatar');
|
||||
|
||||
// 定义模型输出内容容器
|
||||
const botBubbleDiv = document.createElement('div');
|
||||
botBubbleDiv.classList.add('markdown-body');
|
||||
botBubbleDiv.classList.add('bubble');
|
||||
botBubbleDiv.classList.add('bubble-received');
|
||||
botBubbleDiv.innerHTML = Icons.Loading;
|
||||
|
||||
// 在模型响应消息容器中,添加头像
|
||||
botResponseDiv.appendChild(botAvatarDiv);
|
||||
// 在模型响应消息容器中,添加模型响应消息内容
|
||||
botResponseDiv.appendChild(botBubbleDiv);
|
||||
|
||||
this.content.appendChild(botResponseDiv);
|
||||
|
||||
const searchQuery = this.subCategorySelect.value === "all" ? `${this.querySelect.value}:${message}` : `cat:${this.subCategorySelect.value} AND ${this.querySelect.value}:${message}`;
|
||||
const start = (this.currentPage - 1) * this.pageSize;
|
||||
fetch(
|
||||
`https://export.arxiv.org/api/query?search_query=${encodeURIComponent(searchQuery)}&start=${start}&max_results=${this.pageSize}&sortBy=submittedDate&sortOrder=descending`
|
||||
)
|
||||
.then(response => response.text())
|
||||
.then(xmlData => {
|
||||
const arxivs = this.parseXmlResponse(xmlData);
|
||||
botBubbleDiv.innerHTML = "";
|
||||
arxivs.items.forEach(arxiv => {
|
||||
const arxivItem = document.createElement('div');
|
||||
const title = document.createElement('h3');
|
||||
title.textContent = arxiv.title;
|
||||
arxivItem.appendChild(title);
|
||||
const authors = document.createElement('p');
|
||||
authors.textContent = `作者:${arxiv.authors}`;
|
||||
arxivItem.appendChild(authors);
|
||||
const published = document.createElement('p');
|
||||
published.textContent = `日期:${arxiv.published}`;
|
||||
arxivItem.appendChild(published);
|
||||
const summary = document.createElement('p');
|
||||
summary.textContent = `摘要:${arxiv.summary}`;
|
||||
arxivItem.appendChild(summary);
|
||||
const link = document.createElement('a');
|
||||
link.style.margin = '5px';
|
||||
link.textContent = '查看原文';
|
||||
link.addEventListener('click', () => {
|
||||
window.open(arxiv.link, '_blank');
|
||||
});
|
||||
arxivItem.appendChild(link);
|
||||
const pdf = document.createElement('a');
|
||||
pdf.style.margin = '5px';
|
||||
pdf.textContent = '查看论文';
|
||||
pdf.addEventListener('click', () => {
|
||||
const modal = new FullScreenModal(arxiv.title);
|
||||
const body = document.createElement('div');
|
||||
body.classList.add("uai-file-preview-modal-body");
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.src = arxiv.pdf;
|
||||
body.appendChild(iframe);
|
||||
modal.modalBody.appendChild(body);
|
||||
modal.show();
|
||||
});
|
||||
arxivItem.appendChild(pdf);
|
||||
const ref = document.createElement('a');
|
||||
ref.style.margin = '5px';
|
||||
ref.textContent = '添加引用';
|
||||
ref.addEventListener('click', () => {
|
||||
const {
|
||||
state: { selection }
|
||||
} = this.event.editor;
|
||||
|
||||
this.event.editor.commands.insertContentAt(selection.from, {
|
||||
type: 'file',
|
||||
attrs: {
|
||||
['url']: arxiv.pdf,
|
||||
name: `${arxiv.title}.pdf`,
|
||||
size: 0,
|
||||
type: "application/pdf",
|
||||
previewType: "application/pdf",
|
||||
},
|
||||
});
|
||||
});
|
||||
arxivItem.appendChild(ref);
|
||||
botBubbleDiv.appendChild(arxivItem);
|
||||
botBubbleDiv.appendChild(document.createElement('hr'));
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('arXiv API error:', error);
|
||||
});
|
||||
}
|
||||
|
||||
parseXmlResponse(xml: string) {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(xml, 'application/xml');
|
||||
|
||||
const entries = Array.from(doc.querySelectorAll('entry'));
|
||||
return {
|
||||
total: parseInt(doc.querySelector('opensearch>totalResults')?.textContent || '0'),
|
||||
items: entries.map(entry => ({
|
||||
title: entry.querySelector('title')?.textContent?.trim() || '',
|
||||
authors: Array.from(entry.querySelectorAll('author')).map(a =>
|
||||
a.querySelector('name')?.textContent?.trim() || ''
|
||||
).join(', '),
|
||||
published: new Date(
|
||||
entry.querySelector('published')?.textContent || ''
|
||||
).toLocaleDateString(),
|
||||
summary: entry.querySelector('summary')?.textContent?.trim() || '',
|
||||
link: entry.querySelector('link[type="text/html"]')?.getAttribute('href') || '',
|
||||
pdf: entry.querySelector('link[type="application/pdf"]')?.getAttribute('href') || '',
|
||||
}))
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ export class ChatContainer extends HTMLElement implements UAIEditorEventListener
|
||||
// 初始化标题
|
||||
this.chatTitle = document.createElement("div");
|
||||
this.chatTitle.classList.add("uai-pannel-title");
|
||||
this.chatTitle.innerHTML = `<img src="${titleIcon}" width="18" /> ${t('ai.chat.title')}`
|
||||
this.chatTitle.innerHTML = `<img src="${titleIcon}" height="24" width="24"/> ${t('ai.chat.title')}`
|
||||
this.container.appendChild(this.chatTitle);
|
||||
|
||||
// 初始化关闭按钮
|
||||
|
||||
@@ -51,7 +51,7 @@ export class ImageContainer extends HTMLElement implements UAIEditorEventListene
|
||||
// 初始化标题
|
||||
this.imageTitle = document.createElement("div");
|
||||
this.imageTitle.classList.add("uai-pannel-title");
|
||||
this.imageTitle.innerHTML = `<img src="${titleIcon}" width="18" /> ${t('ai.image.title')}`;
|
||||
this.imageTitle.innerHTML = `<img src="${titleIcon}" height="24" width="24"/> ${t('ai.image.title')}`;
|
||||
this.container.appendChild(this.imageTitle);
|
||||
|
||||
// 初始化关闭容器按钮
|
||||
|
||||
@@ -34,7 +34,7 @@ export class TocContainer extends HTMLElement implements UAIEditorEventListener
|
||||
// 初始化标题
|
||||
this.tocTitle = document.createElement("div");
|
||||
this.tocTitle.classList.add("uai-pannel-title");
|
||||
this.tocTitle.innerHTML = `<img src="${titleIcon}" width="18" /> ${t('toc.title')}`;
|
||||
this.tocTitle.innerHTML = `<img src="${titleIcon}" height="24" width="24"/> ${t('toc.title')}`;
|
||||
this.container.appendChild(this.tocTitle);
|
||||
|
||||
// 初始化关闭容器按钮
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Header } from "../components/Header.ts";
|
||||
import { Editor } from "../components/Editor.ts";
|
||||
import { Footer } from "../components/Footer.ts";
|
||||
|
||||
import { ArxivContainer } from "./containers/ArxivContainer.ts";
|
||||
import { ChatContainer } from "../components/containers/ChatContainer.ts";
|
||||
import { ImageContainer } from "../components/containers/ImageContainer.ts";
|
||||
import { TocContainer } from "../components/containers/TocContainer.ts";
|
||||
@@ -80,6 +81,7 @@ import { DeleteRow } from "./menus/toolbar/table/DeleteRow.ts";
|
||||
import { DeleteTable } from "./menus/toolbar/table/DeleteTable.ts";
|
||||
|
||||
import { Diagrams } from "./menus/toolbar/tools/Diagrams.ts";
|
||||
import { ToggleArxiv } from "./menus/toolbar/tools/ToggleArxiv.ts";
|
||||
|
||||
import { ToggleToc } from "./menus/toolbar/page/ToggleToc.ts";
|
||||
import { BackgroundColor } from "./menus/toolbar/page/BackgroundColor.ts";
|
||||
@@ -119,6 +121,7 @@ defineCustomElement('uai-editor-header', Header);
|
||||
defineCustomElement('uai-editor-editor', Editor);
|
||||
defineCustomElement('uai-editor-footer', Footer);
|
||||
|
||||
defineCustomElement('uai-editor-arxiv-container', ArxivContainer);
|
||||
defineCustomElement('uai-editor-chat-container', ChatContainer);
|
||||
defineCustomElement('uai-editor-image-container', ImageContainer);
|
||||
defineCustomElement('uai-editor-toc-container', TocContainer);
|
||||
@@ -192,6 +195,7 @@ defineCustomElement('uai-editor-table-menu-delete-row', DeleteRow);
|
||||
defineCustomElement('uai-editor-table-menu-delete-table', DeleteTable);
|
||||
|
||||
defineCustomElement('uai-editor-tools-menu-diagrams', Diagrams);
|
||||
defineCustomElement('uai-editor-tools-menu-toggle-arxiv', ToggleArxiv);
|
||||
|
||||
defineCustomElement('uai-editor-page-menu-toggle-toc', ToggleToc);
|
||||
defineCustomElement('uai-editor-page-menu-background-color', BackgroundColor);
|
||||
|
||||
@@ -67,6 +67,7 @@ import { DeleteRow } from "./table/DeleteRow.ts";
|
||||
import { DeleteTable } from "./table/DeleteTable.ts";
|
||||
|
||||
import { Diagrams } from "./tools/Diagrams.ts";
|
||||
import { ToggleArxiv } from "./tools/ToggleArxiv.ts";
|
||||
|
||||
import { ToggleToc } from "./page/ToggleToc.ts";
|
||||
import { BackgroundColor } from "./page/BackgroundColor.ts";
|
||||
@@ -183,6 +184,7 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
|
||||
|
||||
// 工具菜单
|
||||
toolsMenuDiagrams!: Diagrams;
|
||||
toolsMenuToggleArxiv!: ToggleArxiv;
|
||||
|
||||
// 页面菜单
|
||||
pageMenuToggleToc!: ToggleToc;
|
||||
@@ -266,7 +268,7 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
|
||||
this.classicScrollableContainer.appendChild(this.classicMenuAIScrollable);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
this.classicScrollableContainer = document.createElement("div");
|
||||
this.classicScrollableContainer.classList.add("uai-classic-scrollable-container");
|
||||
this.classicMenu.appendChild(this.classicScrollableContainer);
|
||||
@@ -450,6 +452,9 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
|
||||
this.toolsMenuDiagrams = new Diagrams({ menuType: "button", enable: true, header: "classic", hideText: false });
|
||||
this.eventComponents.push(this.toolsMenuDiagrams);
|
||||
|
||||
this.toolsMenuToggleArxiv = new ToggleArxiv({ menuType: "button", enable: true, header: "classic", hideText: false });
|
||||
this.eventComponents.push(this.toolsMenuToggleArxiv);
|
||||
|
||||
this.pageMenuToggleToc = new ToggleToc({ menuType: "button", enable: true, header: "classic", hideText: false });
|
||||
this.eventComponents.push(this.pageMenuToggleToc);
|
||||
|
||||
@@ -627,6 +632,11 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
|
||||
group1.classList.add("uai-classic-virtual-group");
|
||||
this.classicMenuToolGroup.appendChild(group1);
|
||||
group1.appendChild(this.toolsMenuDiagrams);
|
||||
|
||||
const group2 = document.createElement("div");
|
||||
group2.classList.add("uai-classic-virtual-group");
|
||||
this.classicMenuToolGroup.appendChild(group2);
|
||||
group2.appendChild(this.toolsMenuToggleArxiv);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -70,6 +70,7 @@ import { DeleteRow } from "./table/DeleteRow.ts";
|
||||
import { DeleteTable } from "./table/DeleteTable.ts";
|
||||
|
||||
import { Diagrams } from "./tools/Diagrams.ts";
|
||||
import { ToggleArxiv } from "./tools/ToggleArxiv.ts";
|
||||
|
||||
import { ToggleToc } from "./page/ToggleToc.ts";
|
||||
import { BackgroundColor } from "./page/BackgroundColor.ts";
|
||||
@@ -185,6 +186,7 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener {
|
||||
|
||||
// 工具菜单
|
||||
toolsMenuDiagrams!: Diagrams;
|
||||
toolsMenuToggleArxiv!: ToggleArxiv;
|
||||
|
||||
// 页面菜单
|
||||
pageMenuToggleToc!: ToggleToc;
|
||||
@@ -471,6 +473,9 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener {
|
||||
this.toolsMenuDiagrams = new Diagrams({ menuType: "button", enable: true, huge: true, hideText: false });
|
||||
this.eventComponents.push(this.toolsMenuDiagrams);
|
||||
|
||||
this.toolsMenuToggleArxiv = new ToggleArxiv({ menuType: "button", enable: true, huge: true, hideText: false });
|
||||
this.eventComponents.push(this.toolsMenuToggleArxiv);
|
||||
|
||||
this.pageMenuToggleToc = new ToggleToc({ menuType: "button", enable: true, huge: true, hideText: false });
|
||||
this.eventComponents.push(this.pageMenuToggleToc);
|
||||
|
||||
@@ -734,6 +739,11 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener {
|
||||
group1.classList.add("uai-ribbon-virtual-group");
|
||||
this.ribbonMenuToolGroup.appendChild(group1);
|
||||
group1.appendChild(this.toolsMenuDiagrams);
|
||||
|
||||
const group2 = document.createElement("div");
|
||||
group2.classList.add("uai-ribbon-virtual-group");
|
||||
this.ribbonMenuToolGroup.appendChild(group2);
|
||||
group2.appendChild(this.toolsMenuToggleArxiv);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) 2024-present AI-Labs
|
||||
|
||||
// @ ts-nocheck
|
||||
import { EditorEvents } from "@tiptap/core";
|
||||
|
||||
import { t } from "i18next";
|
||||
|
||||
import { UAIEditorEventListener, UAIEditorOptions, InnerEditor } from "../../../../core/UAIEditor.ts";
|
||||
import { MenuButton, MenuButtonOptions } from "../../MenuButton.ts";
|
||||
|
||||
import icon from "../../../../assets/icons/arxiv.svg";
|
||||
|
||||
/**
|
||||
* 人工智能菜单:聊天
|
||||
*/
|
||||
export class ToggleArxiv extends HTMLElement implements UAIEditorEventListener {
|
||||
// 按钮选项
|
||||
menuButtonOptions: MenuButtonOptions = {
|
||||
menuType: "button",
|
||||
enable: true,
|
||||
icon: icon,
|
||||
hideText: false,
|
||||
text: t('tools.arxiv.title'),
|
||||
tooltip: t('tools.arxiv.title'),
|
||||
}
|
||||
|
||||
// 功能按钮
|
||||
menuButton: MenuButton;
|
||||
|
||||
constructor(options: MenuButtonOptions) {
|
||||
super();
|
||||
|
||||
// 初始化功能按钮选项
|
||||
this.menuButtonOptions = { ...this.menuButtonOptions, ...options };
|
||||
|
||||
// 创建功能按钮
|
||||
this.menuButton = new MenuButton(this.menuButtonOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义创建方法
|
||||
* @param event
|
||||
* @param options
|
||||
*/
|
||||
onCreate(event: EditorEvents["create"], options: UAIEditorOptions) {
|
||||
this.menuButton.onCreate(event, options);
|
||||
this.appendChild(this.menuButton);
|
||||
|
||||
// 定义按钮点击事件,打开人工智能聊天窗口
|
||||
this.addEventListener("click", () => {
|
||||
if (this.menuButtonOptions.enable) {
|
||||
// 判断聊天窗口是否已打开
|
||||
const display = (event.editor as InnerEditor).uaiEditor.arxivContainer.style.display;
|
||||
if (display != "none") {
|
||||
// 如果窗口已打开,则关闭窗口
|
||||
(event.editor as InnerEditor).uaiEditor.arxivContainer.style.display = "none";
|
||||
} else {
|
||||
// 如果窗口没打开,则先关闭其他窗口,再打开聊天窗口
|
||||
(event.editor as InnerEditor).uaiEditor.toggleContainers.forEach(toggle => {
|
||||
toggle.style.display = "none";
|
||||
});
|
||||
(event.editor as InnerEditor).uaiEditor.arxivContainer.style.display = "block";
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义Transaction监听方法
|
||||
* @param event
|
||||
* @param options
|
||||
*/
|
||||
onTransaction(event: EditorEvents["transaction"], options: UAIEditorOptions) {
|
||||
this.menuButton.onTransaction(event, options);
|
||||
}
|
||||
|
||||
onEditableChange(editable: boolean) {
|
||||
this.menuButtonOptions.enable = editable;
|
||||
this.menuButton.onEditableChange(editable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import { Resource } from "i18next";
|
||||
|
||||
import "../components"
|
||||
import { Header } from "../components/Header.ts";
|
||||
import { ArxivContainer } from "../components/containers/ArxivContainer.ts";
|
||||
import { ChatContainer } from "../components/containers/ChatContainer.ts";
|
||||
import { ImageContainer } from "../components/containers/ImageContainer.ts";
|
||||
import { TocContainer } from "../components/containers/TocContainer.ts";
|
||||
@@ -213,6 +214,7 @@ export class UAIEditor {
|
||||
header!: Header;
|
||||
chatContainer!: ChatContainer;
|
||||
imageContainer!: ImageContainer;
|
||||
arxivContainer!: ArxivContainer;
|
||||
tocContainer!: TocContainer;
|
||||
editor!: Editor;
|
||||
footer!: Footer;
|
||||
@@ -358,6 +360,11 @@ export class UAIEditor {
|
||||
this.center.appendChild(this.tocContainer);
|
||||
this.toggleContainers.push(this.tocContainer);
|
||||
|
||||
this.arxivContainer = new ArxivContainer();
|
||||
this.arxivContainer.style.display = "none";
|
||||
this.center.appendChild(this.arxivContainer);
|
||||
this.toggleContainers.push(this.arxivContainer);
|
||||
|
||||
this.chatContainer = new ChatContainer();
|
||||
this.chatContainer.style.display = "none";
|
||||
this.center.appendChild(this.chatContainer);
|
||||
@@ -430,6 +437,7 @@ export class UAIEditor {
|
||||
}
|
||||
this.header.onCreate(event, this.options);
|
||||
this.tocContainer.onCreate(event, this.options);
|
||||
this.arxivContainer.onCreate(event, this.options);
|
||||
this.chatContainer.onCreate(event, this.options);
|
||||
this.imageContainer.onCreate(event, this.options);
|
||||
this.editor.onCreate(event, this.options);
|
||||
@@ -442,6 +450,7 @@ export class UAIEditor {
|
||||
protected onTransaction(event: EditorEvents['transaction']) {
|
||||
this.header.onTransaction(event, this.options);
|
||||
this.tocContainer.onTransaction(event, this.options);
|
||||
this.arxivContainer.onTransaction(event, this.options);
|
||||
this.chatContainer.onTransaction(event, this.options);
|
||||
this.imageContainer.onTransaction(event, this.options);
|
||||
this.editor.onTransaction(event, this.options);
|
||||
|
||||
@@ -138,7 +138,7 @@ export default Node.create({
|
||||
const body = document.createElement('div');
|
||||
body.classList.add("uai-file-preview-modal-body");
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.src = URL.createObjectURL(base64ToBlob(attrs.url, attrs.previewType));
|
||||
iframe.src = attrs.url.startsWith("data") ? URL.createObjectURL(base64ToBlob(attrs.url, attrs.previewType)) : attrs.url;
|
||||
body.appendChild(iframe);
|
||||
modal.modalBody.appendChild(body);
|
||||
modal.show();
|
||||
|
||||
@@ -271,6 +271,10 @@ export const zh = {
|
||||
"edit": "编辑流程图",
|
||||
"loading": "加载中..."
|
||||
},
|
||||
"arxiv": {
|
||||
"text": "论文",
|
||||
"title": "论文搜索",
|
||||
},
|
||||
"mermaid": {
|
||||
"text": "Mermaid",
|
||||
"edit": "编辑 Mermaid",
|
||||
|
||||
@@ -1054,7 +1054,7 @@
|
||||
border-bottom: solid 1px var(--uai-border-color);
|
||||
|
||||
.uai-model-select {
|
||||
height: 24px;
|
||||
height: 32px;
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user