@@ -562,10 +562,11 @@ <h3>批量上传认证文件</h3>
562562
563563 < div style ="border: 2px dashed #ddd; border-radius: 8px; padding: 30px; text-align: center; background-color: #fafafa; margin: 20px 0; cursor: pointer; transition: border-color 0.3s; " id ="uploadArea " onclick ="document.getElementById('fileInput').click() ">
564564 < p style ="margin: 10px 0; font-size: 16px; "> 📁 点击选择文件或拖拽文件到此区域</ p >
565- < p style ="color: #666; font-size: 14px; margin: 5px 0; "> 支持 .json 格式文件</ p >
565+ < p style ="color: #666; font-size: 14px; margin: 5px 0; "> 支持 .json 和 .zip 格式文件</ p >
566+ < p style ="color: #888; font-size: 12px; margin: 5px 0; "> ZIP文件会自动解压提取其中的JSON凭证</ p >
566567 </ div >
567568
568- < input type ="file " id ="fileInput " multiple accept =".json " style ="display: none; " onchange ="handleFileSelect(event) " />
569+ < input type ="file " id ="fileInput " multiple accept =".json,.zip " style ="display: none; " onchange ="handleFileSelect(event) " />
569570
570571 < div id ="fileListSection " class ="hidden ">
571572 < h4 > 选择的文件:</ h4 >
@@ -1441,12 +1442,13 @@ <h3 style="margin: 0; font-size: 16px; color: #333;">设置使用限制</h3>
14411442
14421443 function addFiles ( files ) {
14431444 files . forEach ( file => {
1444- if ( file . type === 'application/json' || file . name . endsWith ( '.json' ) ) {
1445+ if ( file . type === 'application/json' || file . name . endsWith ( '.json' ) ||
1446+ file . type === 'application/zip' || file . name . endsWith ( '.zip' ) ) {
14451447 if ( ! uploadSelectedFiles . find ( f => f . name === file . name && f . size === file . size ) ) {
14461448 uploadSelectedFiles . push ( file ) ;
14471449 }
14481450 } else {
1449- showStatus ( `文件 ${ file . name } 不是有效的JSON文件 ` , 'error' ) ;
1451+ showStatus ( `文件 ${ file . name } 格式不支持,只支持JSON和ZIP文件 ` , 'error' ) ;
14501452 }
14511453 } ) ;
14521454
@@ -1468,10 +1470,13 @@ <h3 style="margin: 0; font-size: 16px; color: #333;">设置使用限制</h3>
14681470 uploadSelectedFiles . forEach ( ( file , index ) => {
14691471 const fileItem = document . createElement ( 'div' ) ;
14701472 fileItem . style . cssText = 'background-color: #f8f9fa; border: 1px solid #e1e4e8; border-radius: 6px; padding: 10px; margin: 5px 0; display: flex; justify-content: space-between; align-items: center;' ;
1473+ const isZip = file . name . endsWith ( '.zip' ) ;
1474+ const fileIcon = isZip ? '📦' : '📄' ;
1475+ const fileType = isZip ? ' (ZIP压缩包)' : ' (JSON文件)' ;
14711476 fileItem . innerHTML = `
14721477 <div>
1473- <span style="font-family: monospace; color: #333; font-size: 14px;">${ file . name } </span>
1474- <span style="color: #666; font-size: 12px; margin-left: 10px;">(${ formatFileSize ( file . size ) } )</span>
1478+ <span style="font-family: monospace; color: #333; font-size: 14px;">${ fileIcon } ${ file . name } </span>
1479+ <span style="color: #666; font-size: 12px; margin-left: 10px;">(${ formatFileSize ( file . size ) } ${ fileType } )</span>
14751480 </div>
14761481 <button onclick="removeFile(${ index } )" style="background: #dc3545; color: white; border: none; border-radius: 4px; padding: 4px 8px; cursor: pointer; font-size: 12px;">删除</button>
14771482 ` ;
@@ -1501,6 +1506,22 @@ <h3 style="margin: 0; font-size: 16px; color: #333;">设置使用限制</h3>
15011506 return ;
15021507 }
15031508
1509+ // 检查文件大小
1510+ const totalSize = uploadSelectedFiles . reduce ( ( sum , file ) => sum + file . size , 0 ) ;
1511+ const maxSize = 200 * 1024 * 1024 ; // 200MB limit
1512+ if ( totalSize > maxSize ) {
1513+ showStatus ( `文件总大小 ${ ( totalSize / 1024 / 1024 ) . toFixed ( 1 ) } MB 超过限制 ${ maxSize / 1024 / 1024 } MB。请分批上传或删除部分文件。` , 'error' ) ;
1514+ return ;
1515+ }
1516+
1517+ // 检查单个文件大小
1518+ for ( const file of uploadSelectedFiles ) {
1519+ if ( file . size > 5 * 1024 * 1024 ) {
1520+ showStatus ( `文件 "${ file . name } " 大小 ${ ( file . size / 1024 / 1024 ) . toFixed ( 1 ) } MB 超过单文件5MB限制` , 'error' ) ;
1521+ return ;
1522+ }
1523+ }
1524+
15041525 const progressSection = document . getElementById ( 'uploadProgressSection' ) ;
15051526 const progressFill = document . getElementById ( 'progressFill' ) ;
15061527 const progressText = document . getElementById ( 'progressText' ) ;
@@ -1511,10 +1532,19 @@ <h3 style="margin: 0; font-size: 16px; color: #333;">设置使用限制</h3>
15111532 uploadSelectedFiles . forEach ( file => {
15121533 formData . append ( 'files' , file ) ;
15131534 } ) ;
1535+
1536+ // 检查是否有ZIP文件,给用户提示
1537+ const hasZipFiles = uploadSelectedFiles . some ( file => file . name . endsWith ( '.zip' ) ) ;
1538+ if ( hasZipFiles ) {
1539+ showStatus ( '正在上传并解压ZIP文件...' , 'info' ) ;
1540+ }
15141541
15151542 try {
15161543 const xhr = new XMLHttpRequest ( ) ;
15171544
1545+ // 设置超时时间 (5分钟)
1546+ xhr . timeout = 300000 ;
1547+
15181548 xhr . upload . onprogress = function ( event ) {
15191549 if ( event . lengthComputable ) {
15201550 const percentComplete = ( event . loaded / event . total ) * 100 ;
@@ -1525,18 +1555,40 @@ <h3 style="margin: 0; font-size: 16px; color: #333;">设置使用限制</h3>
15251555
15261556 xhr . onload = function ( ) {
15271557 if ( xhr . status === 200 ) {
1528- const data = JSON . parse ( xhr . responseText ) ;
1529- showStatus ( `成功上传 ${ data . uploaded_count } 个文件` , 'success' ) ;
1530- clearFiles ( ) ;
1531- progressSection . classList . add ( 'hidden' ) ;
1558+ try {
1559+ const data = JSON . parse ( xhr . responseText ) ;
1560+ showStatus ( `成功上传 ${ data . uploaded_count } 个文件` , 'success' ) ;
1561+ clearFiles ( ) ;
1562+ progressSection . classList . add ( 'hidden' ) ;
1563+ } catch ( e ) {
1564+ showStatus ( '上传失败: 服务器响应格式错误' , 'error' ) ;
1565+ }
15321566 } else {
1533- const error = JSON . parse ( xhr . responseText ) ;
1534- showStatus ( `上传失败: ${ error . error } ` , 'error' ) ;
1567+ try {
1568+ const error = JSON . parse ( xhr . responseText ) ;
1569+ showStatus ( `上传失败: ${ error . detail || error . error || '未知错误' } ` , 'error' ) ;
1570+ } catch ( e ) {
1571+ showStatus ( `上传失败: HTTP ${ xhr . status } - ${ xhr . statusText || '未知错误' } ` , 'error' ) ;
1572+ }
15351573 }
15361574 } ;
15371575
15381576 xhr . onerror = function ( ) {
1539- showStatus ( '上传失败:网络错误' , 'error' ) ;
1577+ console . error ( 'Upload XHR error:' , {
1578+ readyState : xhr . readyState ,
1579+ status : xhr . status ,
1580+ statusText : xhr . statusText ,
1581+ responseText : xhr . responseText ,
1582+ fileCount : uploadSelectedFiles . length ,
1583+ totalSize : ( totalSize / 1024 / 1024 ) . toFixed ( 1 ) + 'MB'
1584+ } ) ;
1585+ showStatus ( `上传失败:连接中断 - 可能原因:文件过多(${ uploadSelectedFiles . length } 个)或网络不稳定。建议分批上传。` , 'error' ) ;
1586+ progressSection . classList . add ( 'hidden' ) ;
1587+ } ;
1588+
1589+ xhr . ontimeout = function ( ) {
1590+ showStatus ( '上传失败:请求超时 - 文件处理时间过长,请减少文件数量或检查网络连接' , 'error' ) ;
1591+ progressSection . classList . add ( 'hidden' ) ;
15401592 } ;
15411593
15421594 xhr . open ( 'POST' , '/auth/upload' ) ;
0 commit comments