Add files via upload

This commit is contained in:
公明
2026-07-03 14:10:14 +08:00
committed by GitHub
parent 6a52ef96f4
commit 011a242acc
8 changed files with 349 additions and 46 deletions
+83 -12
View File
@@ -84,6 +84,7 @@ function initChatFilesPage() {
/* ignore */
}
}
setupChatFilesDragDrop();
loadChatFilesPage();
}
@@ -1226,21 +1227,31 @@ function chatFilesUploadToFolderClick(ev, btn) {
if (inp) inp.click();
}
async function onChatFilesUploadPick(ev) {
const input = ev.target;
const file = input && input.files && input.files[0];
if (!file) return;
const form = new FormData();
form.append('file', file);
function chatFilesResolveUploadTarget() {
const pendingDir = chatFilesPendingUploadDir;
chatFilesPendingUploadDir = '';
if (pendingDir) {
form.append('relativeDir', pendingDir);
} else {
const conv = document.getElementById('chat-files-filter-conv');
if (conv && conv.value.trim()) {
form.append('conversationId', conv.value.trim());
}
return { relativeDir: pendingDir };
}
if (chatFilesGetGroupByMode() === 'folder') {
const dir = chatFilesBrowsePath.join('/');
return dir ? { relativeDir: dir } : {};
}
const conv = document.getElementById('chat-files-filter-conv');
if (conv && conv.value.trim()) {
return { conversationId: conv.value.trim() };
}
return {};
}
async function chatFilesUploadFile(file, target) {
if (!file || chatFilesXHRUploadBusy) return false;
const form = new FormData();
form.append('file', file);
if (target && target.relativeDir) {
form.append('relativeDir', target.relativeDir);
} else if (target && target.conversationId) {
form.append('conversationId', target.conversationId);
}
chatFilesSetUploadBusy(true);
chatFilesSetUploadProgressUI(true, 0, file.name);
@@ -1265,15 +1276,75 @@ async function onChatFilesUploadPick(ev) {
: '上传成功。在列表中点击「复制路径」即可粘贴到对话中引用。';
chatFilesShowToast(msg);
}
return true;
} catch (e) {
alert((e && e.message) ? e.message : String(e));
return false;
} finally {
chatFilesSetUploadBusy(false);
chatFilesSetUploadProgressUI(false);
}
}
async function chatFilesUploadFiles(fileList) {
if (!fileList || !fileList.length || chatFilesXHRUploadBusy) return;
const files = Array.from(fileList).filter(function (f) {
return f && (f.name || f.size > 0);
});
if (!files.length) return;
const target = chatFilesResolveUploadTarget();
for (let i = 0; i < files.length; i++) {
const ok = await chatFilesUploadFile(files[i], target);
if (!ok) break;
}
}
async function onChatFilesUploadPick(ev) {
const input = ev.target;
const files = input && input.files;
if (!files || !files.length) return;
try {
await chatFilesUploadFiles(files);
} finally {
input.value = '';
}
}
let chatFilesDragDropBound = false;
function setupChatFilesDragDrop() {
if (chatFilesDragDropBound) return;
const wrap = document.getElementById('chat-files-list-wrap');
if (!wrap) return;
chatFilesDragDropBound = true;
wrap.addEventListener('dragover', function (e) {
e.preventDefault();
e.stopPropagation();
if (chatFilesXHRUploadBusy) return;
this.classList.add('drag-over');
});
wrap.addEventListener('dragleave', function (e) {
e.preventDefault();
e.stopPropagation();
if (!this.contains(e.relatedTarget)) {
this.classList.remove('drag-over');
}
});
wrap.addEventListener('drop', function (e) {
e.preventDefault();
e.stopPropagation();
this.classList.remove('drag-over');
if (chatFilesXHRUploadBusy) return;
const files = e.dataTransfer && e.dataTransfer.files;
if (files && files.length) {
chatFilesUploadFiles(files).catch(function (err) {
if (err) alert((err && err.message) ? err.message : String(err));
});
}
});
}
// 语言切换后重新渲染列表:表头与「更多」菜单由 JS 拼接,无 data-i18n,需用当前语言的 t() 再生成一遍
document.addEventListener('languagechange', function () {
if (typeof window.currentPage !== 'function') return;
+30 -19
View File
@@ -137,9 +137,12 @@ function normalizeHitlMode(mode) {
}
function defaultHitlConfig() {
const serverReviewer = (typeof window !== 'undefined' && window.csaiHitlDefaultReviewer)
? window.csaiHitlDefaultReviewer
: 'human';
return {
mode: HITL_MODE_OFF,
reviewer: 'human',
reviewer: normalizeHitlReviewer(serverReviewer),
sensitiveTools: '',
updatedAt: ''
};
@@ -315,16 +318,18 @@ async function onHitlReviewerChanged(reviewer) {
const cfg = readHitlConfigFromForm();
const cid = typeof currentConversationId === 'string' ? currentConversationId.trim() : '';
saveHitlConfigForConversation(cid, cfg, { syncGlobalLast: true });
if (cid && typeof window.saveHitlConversationConfig === 'function') {
try {
try {
if (cid && typeof window.saveHitlConversationConfig === 'function') {
await window.saveHitlConversationConfig(cid, cfg);
const ok = typeof window.t === 'function' ? window.t('hitl.pageReviewerSaved') : '审批方已保存。';
showChatToast(ok, 'success');
} catch (e) {
console.warn('onHitlReviewerChanged', e);
const prefix = typeof window.t === 'function' ? window.t('chat.hitlApplyFail') : '同步到服务器失败';
showChatToast(prefix, 'error');
} else if (typeof window.putHitlDefaultReviewer === 'function') {
await window.putHitlDefaultReviewer(cfg.reviewer);
}
const ok = typeof window.t === 'function' ? window.t('hitl.pageReviewerSaved') : '审批方已保存。';
showChatToast(ok, 'success');
} catch (e) {
console.warn('onHitlReviewerChanged', e);
const prefix = typeof window.t === 'function' ? window.t('chat.hitlApplyFail') : '同步到服务器失败';
showChatToast(prefix, 'error');
}
}
@@ -507,6 +512,7 @@ function chatAgentModeNormalizeStored(stored, cfg) {
if (typeof window !== 'undefined') {
window.csaiHitlGlobalToolWhitelist = window.csaiHitlGlobalToolWhitelist || [];
window.csaiHitlDefaultReviewer = window.csaiHitlDefaultReviewer || 'human';
window.csaiChatAgentMode = {
EINO_MODES: CHAT_AGENT_EINO_MODES,
EINO_SINGLE: CHAT_AGENT_MODE_EINO_SINGLE,
@@ -518,6 +524,7 @@ if (typeof window !== 'undefined') {
window.applyHitlSidebarConfig = applyHitlSidebarConfig;
window.readHitlConfigFromForm = readHitlConfigFromForm;
window.applyHitlConfigToUI = applyHitlConfigToUI;
window.refreshHitlConfigByCurrentConversation = refreshHitlConfigByCurrentConversation;
window.saveHitlConfigForConversation = saveHitlConfigForConversation;
window.getHitlConfigForConversation = getHitlConfigForConversation;
bindHitlSidebarModeListener();
@@ -2020,6 +2027,19 @@ function refreshSystemReadyMessageBubbles() {
});
}
function createMessageAvatar(role) {
const avatar = document.createElement('div');
avatar.className = 'message-avatar';
if (role === 'user') {
avatar.innerHTML = '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><circle cx="12" cy="7" r="4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
} else if (role === 'assistant') {
avatar.innerHTML = '<img src="/static/logo.png" alt="" class="message-avatar-img">';
} else {
avatar.textContent = 'S';
}
return avatar;
}
// 添加消息(options.systemReadyMessage 为 true 时,语言切换会刷新该条文案)
function addMessage(role, content, mcpExecutionIds = null, progressId = null, createdAt = null, options = null) {
const messagesDiv = document.getElementById('chat-messages');
@@ -2030,16 +2050,7 @@ function addMessage(role, content, mcpExecutionIds = null, progressId = null, cr
messageDiv.className = 'message ' + role;
// 创建头像
const avatar = document.createElement('div');
avatar.className = 'message-avatar';
if (role === 'user') {
avatar.textContent = 'U';
} else if (role === 'assistant') {
avatar.textContent = 'A';
} else {
avatar.textContent = 'S';
}
messageDiv.appendChild(avatar);
messageDiv.appendChild(createMessageAvatar(role));
// 创建消息内容容器
const contentWrapper = document.createElement('div');
+62
View File
@@ -231,10 +231,66 @@ async function fetchHitlConversationConfig(conversationId) {
if (!data || !data.hitl) return null;
return {
hitl: data.hitl,
defaultReviewer: hitlReviewerNormalize(data.defaultReviewer || 'human'),
hitlGlobalToolWhitelist: Array.isArray(data.hitlGlobalToolWhitelist) ? data.hitlGlobalToolWhitelist : []
};
}
function applyHitlDefaultReviewerFromServer(reviewer) {
const v = hitlReviewerNormalize(reviewer);
if (typeof window !== 'undefined') {
window.csaiHitlDefaultReviewer = v;
}
if (typeof window.saveHitlLastGlobalConfig === 'function' && typeof window.getHitlLastGlobalConfig === 'function') {
const gl = window.getHitlLastGlobalConfig();
const base = gl && typeof gl === 'object'
? gl
: { mode: 'off', sensitiveTools: '', updatedAt: '' };
window.saveHitlLastGlobalConfig(Object.assign({}, base, {
reviewer: v,
updatedAt: new Date().toISOString()
}));
}
return v;
}
async function fetchHitlDefaultReviewer() {
const resp = await hitlApiFetch('/api/hitl/default-reviewer', { credentials: 'same-origin' });
if (!resp.ok) {
return applyHitlDefaultReviewerFromServer('human');
}
const data = await resp.json();
return applyHitlDefaultReviewerFromServer(data && data.defaultReviewer);
}
async function putHitlDefaultReviewer(reviewer) {
const normalized = hitlReviewerNormalize(reviewer);
const resp = await hitlApiFetch('/api/hitl/default-reviewer', {
method: 'PUT',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ reviewer: normalized })
});
if (!resp.ok) {
const msg = await readHitlApiError(resp);
throw new Error(msg || ('HTTP ' + resp.status));
}
const data = await resp.json();
return applyHitlDefaultReviewerFromServer(data && data.defaultReviewer);
}
async function initHitlDefaultReviewerFromServer() {
try {
await fetchHitlDefaultReviewer();
if (!getCurrentConversationIdForHitl() && typeof window.refreshHitlConfigByCurrentConversation === 'function') {
window.refreshHitlConfigByCurrentConversation();
}
refreshHitlPageReviewerBar();
} catch (e) {
console.warn('initHitlDefaultReviewerFromServer', e);
}
}
/** 无会话时:将免审批工具合并进服务端 config.yaml,返回更新后的全局白名单数组 */
async function mergeHitlGlobalToolWhitelist(sensitiveTools) {
const list = Array.isArray(sensitiveTools) ? sensitiveTools : [];
@@ -462,6 +518,9 @@ async function syncHitlConfigFromServer(conversationId) {
const pack = await fetchHitlConversationConfig(conversationId);
if (!pack || !pack.hitl) return;
const cfg = pack.hitl;
if (pack.defaultReviewer) {
applyHitlDefaultReviewerFromServer(pack.defaultReviewer);
}
const globalWL = pack.hitlGlobalToolWhitelist || [];
if (typeof window !== 'undefined') {
window.csaiHitlGlobalToolWhitelist = globalWL;
@@ -1460,6 +1519,7 @@ document.addEventListener('DOMContentLoaded', function () {
if (typeof window.bindHitlReviewerToggleListeners === 'function') {
window.bindHitlReviewerToggleListeners();
}
initHitlDefaultReviewerFromServer();
setTimeout(reconcileHitlUiState, 0);
});
@@ -1478,3 +1538,5 @@ window.mergeHitlGlobalToolWhitelist = mergeHitlGlobalToolWhitelist;
// 由 chat.js 在 loadConversation 内 await 调用;挂到 window 供其它入口显式触发
window.syncHitlConfigFromServer = syncHitlConfigFromServer;
window.fetchHitlDefaultReviewer = fetchHitlDefaultReviewer;
window.putHitlDefaultReviewer = putHitlDefaultReviewer;
+3
View File
@@ -34,6 +34,9 @@
if (el.classList.contains('info-collect-cell-modal')) {
return 'flex';
}
if (el.classList.contains('chat-files-form-modal')) {
return 'flex';
}
if (FLEX_MODAL_IDS.has(el.id)) {
return 'flex';
}