From 774490b47f3a92d5101a5ca6834d85edbba903ef Mon Sep 17 00:00:00 2001 From: potaser Date: Sun, 9 Aug 2026 06:38:53 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=9A=E8=AF=AD=E8=A8=80=E9=A6=96=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/vue3/index_ml.html | 105 +++++++++++++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 6 deletions(-) diff --git a/apps/web/vue3/index_ml.html b/apps/web/vue3/index_ml.html index 8936729a6..ef98e8dcd 100644 --- a/apps/web/vue3/index_ml.html +++ b/apps/web/vue3/index_ml.html @@ -999,6 +999,10 @@ padding: 10px; } + .execution-log-item.assistant .log-content.structured-content { + font-size: 13px; + } + .execution-log-item.assistant .log-content.short-content { font-size: 13px; } @@ -1366,11 +1370,13 @@ -
+

{{ t('拓展分析阶段') }}

+ {{ t('运行结果') }}
{{ t('已写阶段') }} @@ -1431,7 +1437,6 @@ {{ t('运行已发布') }} - {{ t('运行结果') }}
@@ -1780,6 +1785,20 @@ 📂 Select
+ + + @@ -7825,6 +7844,7 @@ RNA-seq KEGG/fgsea 会优先使用物种级 KEGG gene set;没有物种级缓 }); const activeRnaseqScopeId = ref(''); const activeGenotypeScopeId = ref(''); + const lightweightExtensionTestStatus = ref('拖入固定结构文件夹,系统将自动创建 Job、解析环境并开始 upload。'); // 对话消息 const messages = ref([]); @@ -19304,6 +19324,10 @@ compare: [[flesh, peel]]`; }; const extensionFileKey = (file) => `${file?.name || ''}::${file?.size || 0}::${file?.lastModified || 0}`; + const extensionUploadPath = (file) => { + const relative = String(file?.lightweightRelativePath || '').trim().replace(/^\/+/, ''); + return relative || String(file?.name || '').trim(); + }; const appendExtensionFiles = (target, files) => { const current = Array.isArray(target) ? target : []; const merged = [...current]; @@ -19329,6 +19353,53 @@ compare: [[flesh, peel]]`; if (selected.length) ElMessage.success(`已选择 ${selected.length} 个测试数据文件`); event.target.value = ''; }; + const handleLightweightExtensionFolderDrop = (event) => { + const droppedFiles = Array.from(event?.dataTransfer?.files || []); + if (!droppedFiles.length) { + ElMessage.warning('未检测到可用文件'); + return; + } + + const codeExtPattern = /\.(py|r|sh|bash|pl|js|ts|java|c|cc|cpp|go|rs|jl|rb|m|smk|nf|ipynb)$/i; + const dataExtPattern = /\.(fastq|fq|gz|fa|fasta|fna|faa|pep|cds|gff|gff3|gtf|csv|tsv|txt|xlsx|xls|vcf|sam|bam)$/i; + + const normalized = droppedFiles.map((file) => { + const relativePath = file.webkitRelativePath || file.name; + if (!file.lightweightRelativePath) { + Object.defineProperty(file, 'lightweightRelativePath', { + value: relativePath, + configurable: true + }); + } + return file; + }); + + const codeFiles = []; + const dataFiles = []; + normalized.forEach((file) => { + const filePath = extensionUploadPath(file).toLowerCase(); + if (codeExtPattern.test(filePath)) { + codeFiles.push(file); + } else if (dataExtPattern.test(filePath)) { + dataFiles.push(file); + } else { + codeFiles.push(file); + } + }); + + extensionBuild.codeFiles = appendExtensionFiles(extensionBuild.codeFiles, codeFiles); + extensionBuild.dataFiles = appendExtensionFiles(extensionBuild.dataFiles, dataFiles); + + if (!extensionBuild.displayName) { + const firstPath = normalized[0]?.webkitRelativePath || normalized[0]?.name || ''; + const folder = firstPath.includes('/') ? firstPath.split('/')[0] : ''; + if (folder) { + extensionBuild.displayName = folder.replace(/[^a-zA-Z0-9_-]+/g, '_'); + } + } + + ElMessage.success(`已拖入 ${normalized.length} 个文件,已自动填充拓展包`); + }; const removeExtensionFile = (kind, file) => { const key = extensionFileKey(file); if (kind === 'code') { @@ -19363,7 +19434,7 @@ compare: [[flesh, peel]]`; const value = String(path || ''); if (!value.startsWith('/api/extension-stages') && !value.startsWith('/api/extension-stage-runs')) return value; const host = window.location.hostname || '127.0.0.1'; - return `${window.location.protocol}//${host}:7880${value}`; + return `${window.location.protocol}//${host}:${window.location.port}${value}`; }; const extensionApiFetch = async (path, options = {}) => fetch(extensionApiUrl(path), options); const pushExtensionStatus = (message, type = 'info', showDialog = false) => { @@ -19724,8 +19795,8 @@ compare: [[flesh, peel]]`; form.append('extension_id', extensionId); if (hasCommand) form.append('original_command', extensionBuild.command); form.append('operation_token', token); - extensionBuild.codeFiles.forEach(file => form.append('raw_code_files', file)); - extensionBuild.dataFiles.forEach(file => form.append('raw_data_files', file)); + extensionBuild.codeFiles.forEach(file => form.append('raw_code_files', file, extensionUploadPath(file))); + extensionBuild.dataFiles.forEach(file => form.append('raw_data_files', file, extensionUploadPath(file))); if (hasDataPaths) form.append('raw_data_paths', extensionBuild.dataPaths); const response = await extensionApiFetch('/api/lightweight-extension-stages/upload', { method: 'POST', body: form }); if (!response.ok) throw new Error(await extensionApiError(response, '原始包可复现检查提交失败')); @@ -22289,7 +22360,7 @@ compare: [[flesh, peel]]`; addMessage('user', userInput); ragHistory.value.push({ role: 'user', content: userInput, time: new Date().toLocaleTimeString() }); - // 调用当前 bbav5 后端 RAG 代理,随页面端口走同源地址(例如 7880) + // 调用当前 bbav5 后端 RAG 代理,随页面端口走同源地址 const data = await fetchJsonWithTimeout('/api/agent/rag', { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -23523,6 +23594,25 @@ compare: [[flesh, peel]]`; runExtensionStageFromIntent, extensionOutputIcon, openExtensionOutput, + // lightWeightExtensionTest + lightweightExtensionTestStatus, + handleLightweightExtensionFolderDrop: (event) => window.LightWeightExtensionTest && window.LightWeightExtensionTest.handleDrop({ + jobInfo, + extensionBuild, + createNewJob, + appendExtensionFiles, + buildLightweightExtensionStage, + lightweightExtensionTestStatus, + }, event), + handleLightweightExtensionFolderPick: (event) => window.LightWeightExtensionTest && window.LightWeightExtensionTest.handlePick({ + jobInfo, + extensionBuild, + createNewJob, + appendExtensionFiles, + buildLightweightExtensionStage, + lightweightExtensionTestStatus, + }, event), + openLightweightExtensionFolderPicker: () => window.LightWeightExtensionTest && window.LightWeightExtensionTest.openPicker(), methodologyPaperId, methodologyFamily, methodologyBatchDir, @@ -23761,6 +23851,9 @@ compare: [[flesh, peel]]`; document.getElementById('app').style.display = 'block'; console.log('App mounted successfully'); + + +