@@ -9,6 +9,9 @@ let LANG = {
99 Cron : "计划任务" ,
1010}
1111
12+ // 标记流量相关函数已在主JS文件中准备就绪
13+ window . trafficFunctionsReady = true ;
14+
1215function updateLang ( newLang ) {
1316 if ( newLang ) {
1417 LANG = newLang ;
@@ -715,3 +718,197 @@ $(document).ready(() => {
715718 } ) ;
716719 } catch ( error ) { }
717720} ) ;
721+
722+ // ===== 流量数据处理相关函数 =====
723+
724+ /**
725+ * 通过API获取特定服务器的流量数据
726+ * @param {string|number } serverId 服务器ID
727+ * @returns {Promise } API请求Promise
728+ */
729+ function fetchTrafficData ( serverId ) {
730+ return $ . ajax ( {
731+ url : `/api/server/${ serverId } /traffic` ,
732+ type : "GET" ,
733+ contentType : "application/json" ,
734+ } ) . done ( ( resp ) => {
735+ if ( resp . code == 200 ) {
736+ return resp . data ;
737+ } else {
738+ console . error ( "获取流量数据失败:" , resp . message ) ;
739+ return null ;
740+ }
741+ } ) . fail ( ( err ) => {
742+ console . error ( "获取流量数据网络错误:" , err . responseText ) ;
743+ return null ;
744+ } ) ;
745+ }
746+
747+ // 初始化全局流量数据变量
748+ window . serverTrafficData = { } ;
749+ window . lastTrafficUpdateTime = 0 ;
750+
751+ /**
752+ * 从嵌入的JavaScript变量中提取流量数据并进行处理
753+ */
754+ window . extractTrafficData = function ( ) {
755+ try {
756+ // Get traffic data from global variable
757+ const trafficItems = window . serverTrafficRawData || [ ] ;
758+ if ( ! trafficItems || trafficItems . length === 0 ) {
759+ return ;
760+ }
761+
762+ const newTrafficData = { } ;
763+
764+ // Process each traffic data item
765+ trafficItems . forEach ( item => {
766+ if ( item ) {
767+ const rawServerId = item . id ;
768+ const serverName = item . serverName ;
769+ const maxTrafficText = item . max ;
770+ const usedTrafficText = item . used ;
771+ const percentStr = String ( item . percent ) ;
772+ const percent = parseInt ( percentStr ) || 0 ;
773+
774+ // Find matching server
775+ let matchingServer = null ;
776+ if ( window . statusCards && window . statusCards . servers ) {
777+ matchingServer = window . statusCards . servers . find ( s => s . Name === serverName ) ;
778+ }
779+
780+ const serverId = matchingServer ? matchingServer . ID : rawServerId ;
781+
782+ // Normalize unit format
783+ const standardMaxTraffic = window . formatTrafficUnit ( maxTrafficText ) ;
784+ const standardUsedTraffic = window . formatTrafficUnit ( usedTrafficText ) ;
785+
786+ // Convert traffic data to bytes for accurate calculation
787+ const maxTrafficBytes = window . parseTrafficToBytes ( maxTrafficText ) ;
788+ const usedTrafficBytes = window . parseTrafficToBytes ( usedTrafficText ) ;
789+
790+ // Use percent from data attributes
791+ const calculatedPercent = percent ;
792+
793+ // Store data
794+ newTrafficData [ serverId ] = {
795+ max : standardMaxTraffic ,
796+ used : standardUsedTraffic ,
797+ percent : calculatedPercent ,
798+ maxBytes : maxTrafficBytes ,
799+ usedBytes : usedTrafficBytes
800+ } ;
801+
802+ // Store a copy with original ID as well
803+ if ( serverId !== rawServerId ) {
804+ newTrafficData [ rawServerId ] = {
805+ max : standardMaxTraffic ,
806+ used : standardUsedTraffic ,
807+ percent : calculatedPercent ,
808+ maxBytes : maxTrafficBytes ,
809+ usedBytes : usedTrafficBytes
810+ } ;
811+ }
812+ }
813+ } ) ;
814+
815+ window . serverTrafficData = newTrafficData ;
816+ window . lastTrafficUpdateTime = Date . now ( ) ;
817+
818+ // Update Vue component if available
819+ if ( window . statusCards && typeof window . statusCards . updateTrafficData === 'function' ) {
820+ window . statusCards . updateTrafficData ( ) ;
821+ }
822+ } catch ( e ) {
823+ console . error ( 'Error extracting traffic data:' , e ) ;
824+ }
825+ } ;
826+
827+ /**
828+ * 将流量字符串(如"1.5MB")解析为字节数
829+ * @param {string } trafficStr 流量字符串
830+ * @returns {number } 字节数
831+ */
832+ window . parseTrafficToBytes = function ( trafficStr ) {
833+ if ( ! trafficStr ) return 0 ;
834+
835+ // 清理字符串,去除空格并转为大写,便于处理
836+ const cleanStr = trafficStr . replace ( / \s + / g, '' ) . toUpperCase ( ) ;
837+
838+ // 匹配标准格式 数字+单位
839+ let match = cleanStr . match ( / ^ ( [ \d . , ] + ) ( [ K M G T P E Z Y ] ? B ) $ / i) ;
840+
841+ // 如果没匹配到,尝试没有B的格式(如 1.5M)
842+ if ( ! match ) {
843+ match = cleanStr . match ( / ^ ( [ \d . , ] + ) ( [ K M G T P E Z Y ] ) $ / i) ;
844+ if ( match ) {
845+ match [ 2 ] = match [ 2 ] + 'B' ; // 补充B单位
846+ }
847+ }
848+
849+ // 如果还是没匹配到,返回0
850+ if ( ! match ) {
851+ console . warn ( '无法解析流量字符串:' , trafficStr ) ;
852+ return 0 ;
853+ }
854+
855+ // 处理千位分隔符
856+ const value = parseFloat ( match [ 1 ] . replace ( / , / g, '' ) ) ;
857+ const unit = match [ 2 ] . toUpperCase ( ) ;
858+
859+ // 单位换算表
860+ const units = {
861+ 'B' : 1 ,
862+ 'KB' : 1024 ,
863+ 'MB' : 1024 * 1024 ,
864+ 'GB' : 1024 * 1024 * 1024 ,
865+ 'TB' : 1024 * 1024 * 1024 * 1024 ,
866+ 'PB' : 1024 * 1024 * 1024 * 1024 * 1024 ,
867+ 'EB' : 1024 * 1024 * 1024 * 1024 * 1024 * 1024 ,
868+ 'ZB' : 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 ,
869+ 'YB' : 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024
870+ } ;
871+
872+ return value * ( units [ unit ] || 1 ) ;
873+ } ;
874+
875+ /**
876+ * 格式化流量单位,确保统一格式(如总是包含B后缀)
877+ * @param {string } trafficStr 流量字符串
878+ * @returns {string } 格式化后的流量字符串
879+ */
880+ window . formatTrafficUnit = function ( trafficStr ) {
881+ if ( ! trafficStr ) return '0B' ;
882+
883+ // 如果已经是标准格式,直接返回
884+ if ( / ^ [ \d . , ] + \s * [ K M G T P E Z Y ] B $ / i. test ( trafficStr ) ) {
885+ return trafficStr ;
886+ }
887+
888+ // 处理省略了B的情况(如1.5M)
889+ const match = trafficStr . match ( / ^ ( [ \d . , ] + ) \s * ( [ K M G T P E Z Y ] ) $ / i) ;
890+ if ( match ) {
891+ return `${ match [ 1 ] } ${ match [ 2 ] . toUpperCase ( ) } B` ;
892+ }
893+
894+ // 解析为字节数并重新格式化
895+ const bytes = window . parseTrafficToBytes ( trafficStr ) ;
896+ if ( bytes > 0 ) {
897+ const i = Math . floor ( Math . log ( bytes ) / Math . log ( 1024 ) ) ;
898+ const sizes = [ "B" , "KB" , "MB" , "GB" , "TB" , "PB" , "EB" , "ZB" , "YB" ] ;
899+ return parseFloat ( ( bytes / Math . pow ( 1024 , i ) ) . toFixed ( 2 ) ) + sizes [ i ] ;
900+ }
901+
902+ return trafficStr ; // 无法识别时返回原始字符串
903+ } ;
904+
905+ /**
906+ * 初始化流量数据提取和更新
907+ */
908+ $ ( document ) . ready ( function ( ) {
909+ // 立即提取数据
910+ setTimeout ( window . extractTrafficData , 500 ) ;
911+
912+ // 设置定期更新数据的间隔(每30秒)
913+ setInterval ( window . extractTrafficData , 30000 ) ;
914+ } ) ;
0 commit comments