@@ -664,6 +664,9 @@ class Application {
664664 ".click-text:hover" : [
665665 `text-decoration: none;
666666 background-color: var(--text-shadow)`
667+ ] ,
668+ ".summary_paper p" : [
669+ `white-space: break-spaces`
667670 ]
668671 }
669672 this . $side = this . createElement ( "aside" ) . class ( "side" )
@@ -2067,16 +2070,244 @@ class Modal extends Element {
20672070 }
20682071 close ( ) {
20692072 if ( ! this . opened ) return this
2070- this . _container . clear ( )
20712073 this . opened = false ;
20722074 this . timer = app . runTaskLater ( ( ) => {
2075+ this . _container . clear ( )
20732076 document . body . removeChild ( this . valueOf ( ) )
20742077 } , 250 )
20752078 document . body . style . overflow = "auto"
20762079 this . removeClass ( "open" )
20772080 return this
20782081 }
20792082}
2083+ class PanelModal extends Modal {
2084+ constructor ( ) {
2085+ super ( )
2086+ this . _Styles = {
2087+ ".modal-panel-header" : [
2088+ `margin: 0px;
2089+ font-family: inherit;
2090+ line-height: 1.6;
2091+ flex: 0 0 auto;
2092+ font-weight: 600;
2093+ font-size: 16px;
2094+ padding: 32px 32px 16px;
2095+ display: flex;
2096+ -webkit-box-pack: justify;
2097+ justify-content: space-between;
2098+ -webkit-box-align: center;
2099+ align-items: center;`
2100+ ] ,
2101+ ".modal-container" : [
2102+ `background-color: rgb(255, 255, 255);
2103+ display: block;
2104+ border-radius: 12px;
2105+ width: 800px;
2106+ max-width: 800px;
2107+ margin: 32px;
2108+ overflow-y: auto;
2109+ height: auto;
2110+ max-height: calc(100% - 64px);`
2111+ ] ,
2112+ ".modal-panel-close" : [
2113+ `display: inline-flex;
2114+ -webkit-box-align: center;
2115+ align-items: center;
2116+ -webkit-box-pack: center;
2117+ justify-content: center;
2118+ position: relative;
2119+ box-sizing: border-box;
2120+ -webkit-tap-highlight-color: transparent;
2121+ background-color: transparent;
2122+ outline: 0px;
2123+ border: 0px;
2124+ margin: 0px;
2125+ cursor: pointer;
2126+ user-select: none;
2127+ vertical-align: middle;
2128+ appearance: none;
2129+ text-decoration: none;
2130+ text-align: center;
2131+ flex: 0 0 auto;
2132+ font-size: 1.5rem;
2133+ padding: 8px;
2134+ border-radius: 50%;
2135+ overflow: visible;
2136+ transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
2137+ color: rgba(0, 0, 0, 0.5);`
2138+ ] ,
2139+ ".modal-panel-close:hover" : [
2140+ `background-color: rgba(0, 0, 0, 0.04)`
2141+ ] ,
2142+ ".modal-panel-title" : [
2143+ `margin: 0px;
2144+ font-family: inherit;
2145+ line-height: 1.6;
2146+ flex: 0 0 auto;
2147+ font-weight: 600;
2148+ font-size: 16px;
2149+ display: flex;
2150+ -webkit-box-pack: justify;
2151+ justify-content: space-between;
2152+ -webkit-box-align: center;
2153+ align-items: center;`
2154+ ] ,
2155+ ".modal-panel-footer" : [
2156+ `display: flex;
2157+ -webkit-box-align: center;
2158+ align-items: center;
2159+ -webkit-box-pack: end;
2160+ justify-content: flex-end;
2161+ flex: 0 0 auto;
2162+ padding: 0px 32px 32px;`
2163+ ] ,
2164+ ".modal-panel-confirm-button" : [
2165+ `display: inline-flex;
2166+ -webkit-box-align: center;
2167+ align-items: center;
2168+ -webkit-box-pack: center;
2169+ justify-content: center;
2170+ position: relative;
2171+ box-sizing: border-box;
2172+ -webkit-tap-highlight-color: transparent;
2173+ outline: 0px;
2174+ border: 0px;
2175+ margin: 0px;
2176+ cursor: pointer;
2177+ user-select: none;
2178+ vertical-align: middle;
2179+ appearance: none;
2180+ text-decoration: none;
2181+ font-family: inherit;
2182+ font-weight: 500;
2183+ font-size: 0.875rem;
2184+ line-height: 1.75;
2185+ text-transform: uppercase;
2186+ min-width: 64px;
2187+ padding: 6px 16px;
2188+ border-radius: 4px;
2189+ color: rgb(255, 255, 255);
2190+ background-color: rgb(15, 198, 194);
2191+ box-shadow: none;
2192+ transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, border-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
2193+ margin-left: 8px;`
2194+ ] ,
2195+ ".modal-panel-confirm-button:hover" : [
2196+ `text-decoration: none;
2197+ background-color: rgb(10, 138, 135);`
2198+ ] ,
2199+ ".modal-panel-cancel-button" : [
2200+ `display: inline-flex;
2201+ -webkit-box-align: center;
2202+ align-items: center;
2203+ -webkit-box-pack: center;
2204+ justify-content: center;
2205+ position: relative;
2206+ box-sizing: border-box;
2207+ -webkit-tap-highlight-color: transparent;
2208+ background-color: transparent;
2209+ outline: 0px;
2210+ border: 0px;
2211+ margin: 0px;
2212+ cursor: pointer;
2213+ user-select: none;
2214+ vertical-align: middle;
2215+ appearance: none;
2216+ text-decoration: none;
2217+ font-family: inherit;
2218+ font-weight: 500;
2219+ font-size: 0.875rem;
2220+ line-height: 1.75;
2221+ text-transform: uppercase;
2222+ min-width: 64px;
2223+ padding: 6px 8px;
2224+ border-radius: 4px;
2225+ transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, border-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
2226+ color: rgb(15, 198, 194);
2227+ box-shadow: none;`
2228+ ] ,
2229+ ".modal-panel-padding-button" : [
2230+ `padding-left: 30px;
2231+ padding-right: 30px;`
2232+ ] ,
2233+ ".modal-panel-cancel-button:hover" : [
2234+ `background-color: rgba(15, 198, 194, 0.04);`
2235+ ] ,
2236+ ".modal-panel-body" : [
2237+ `flex: 1 1 auto;
2238+ overflow-y: auto;
2239+ height: auto;
2240+ width: 100%;
2241+ padding-left: 32px;
2242+ padding-right: 32px;`
2243+ ]
2244+ }
2245+ this . _header = app . createElement ( "div" ) . class ( "modal-panel-header" )
2246+ this . _title = app . createElement ( "div" ) . class ( "modal-panel-title" )
2247+ this . _close = app . createElement ( "i" ) . class ( "bx" , "bx-x" , "modal-panel-close" ) . event ( "click" , ( ) => {
2248+ this . close ( )
2249+ } )
2250+ this . _footer = app . createElement ( "div" ) . class ( "modal-panel-footer" )
2251+ this . _body = app . createElement ( "div" ) . class ( "modal-panel-body" )
2252+ this . _cancel = app . createElement ( "button" ) . class ( "modal-panel-cancel-button" , "modal-panel-padding-button" ) . setI18N ( "button.cancel" ) . event ( "click" , ( ) => {
2253+ this . close ( )
2254+ } )
2255+ this . _confirm = app . createElement ( "button" ) . class ( "modal-panel-confirm-button" , "modal-panel-padding-button" ) . setI18N ( "button.confirm" ) . event ( "click" , ( ) => {
2256+ this . _confirm_handler && this . _confirm_handler ( )
2257+ this . close ( )
2258+ } )
2259+ this . _confirm_handler = null ;
2260+ this . container = [
2261+ this . _header . append (
2262+ this . _title ,
2263+ this . _close
2264+ ) ,
2265+ this . _body ,
2266+ this . _footer . append (
2267+ this . _cancel ,
2268+ this . _confirm
2269+ )
2270+ ]
2271+ app . setStyles ( this . _Styles )
2272+ }
2273+ body ( ...elements ) {
2274+ this . _body . append ( ...elements )
2275+ return this
2276+ }
2277+ open ( ) {
2278+ this . _cancel . setStyle ( "display" , "none" )
2279+ super . open ( )
2280+ super . body ( ...this . container )
2281+ return this
2282+ }
2283+ title ( text ) {
2284+ this . _title . setText ( text )
2285+ this . _title . setI18N ( null )
2286+ return this
2287+ }
2288+ title_i18n ( i18n , params ) {
2289+ this . _title . setI18N ( i18n , params )
2290+ return this
2291+ }
2292+ title_t18n ( params ) {
2293+ this . _title . t18n ( params )
2294+ return this
2295+ }
2296+ close ( ) {
2297+ this . _title . setI18N ( null )
2298+ this . _confirm_handler = null
2299+ this . _body . clear ( )
2300+ super . close ( )
2301+ return this
2302+ }
2303+ setCancel ( visible ) {
2304+ this . _cancel . setStyle ( "display" , visible ? "" : "none" )
2305+ return this
2306+ }
2307+ setConfirmHandler ( handler ) {
2308+ this . _confirm_handler = handler
2309+ }
2310+ }
20802311const $I18N = new I18NManager ( )
20812312$I18N . addLangs ( "zh_cn" , {
20822313 "dashboard.uptime" : "运行时间" ,
@@ -2094,7 +2325,6 @@ $I18N.addLangs("zh_cn", {
20942325 "dashboard.bytes.hourly" : "每小时下载量" ,
20952326 "dashboard.download.daily" : "30 天内下载数" ,
20962327 "dashboard.bytes.daily" : "30 天内下载量" ,
2097- "unit.hourly" : "%hour% 时" ,
20982328 "dashboard.io.hits" : "I/O 击中数" ,
20992329 "dashboard.cache.hits" : "缓存击中数" ,
21002330 "dashboard.io.bytes" : "I/O 击中量" ,
@@ -2121,6 +2351,9 @@ $I18N.addLangs("zh_cn", {
21212351 "dashboard.memory" : "内存使用" ,
21222352 "dashboard.connections" : "连接数" ,
21232353 "dashboard.basic.summary" : "统计总结" ,
2354+ "unit.hourly" : "%hour% 时" ,
2355+ "button.confirm" : "确定" ,
2356+ "button.cancel" : "取消" ,
21242357 "see.more" : "查看更多" ,
21252358 "menu.dashboard" : "数据统计" ,
21262359 "menu.master" : "主控面板" ,
@@ -2791,7 +3024,7 @@ $github = (() => {
27913024 return ""
27923025} ) ( ) ;
27933026app = new Application ( )
2794- const modal = new Modal ( )
3027+ const modal = new PanelModal ( )
27953028$preloader = new Preloader ( )
27963029$progress = new ProgressBar ( ) ;
27973030const logger = new Console ( )
@@ -2866,7 +3099,73 @@ app.$Menu.add("dashboard", new class {
28663099 }
28673100 } )
28683101 this . summary = app . createElement ( "button" ) . class ( "click-text" ) . setI18N ( "dashboard.basic.summary" ) . event ( "click" , ( ) => {
2869- modal . open ( )
3102+ modal . open ( ) . title ( "统计" )
3103+ $progress . set ( 50 )
3104+ $MainSocket . send ( "summary_basic" ) . then ( ( data ) => {
3105+ $progress . set ( 90 )
3106+ const main = app . createElement ( "div" ) . class ( "summary_paper" ) , print = ( message , speed ) => {
3107+ var cur = app . createElement ( "p" )
3108+ var cur_presents = [ ]
3109+ var cur_text = ""
3110+ var cur_padding = 1
3111+ var remove_index = 0
3112+ main . append ( cur )
3113+ for ( let i = 0 ; i < message . length ; i ++ ) {
3114+ var msg = message [ i ] ;
3115+ if ( msg == "\t" || msg == "\n" || msg == "\0" || msg == "\b" || msg == "\r" ) remove_index ++
3116+ setTimeout ( ( ) => {
3117+ var msg = message [ i ] ;
3118+ if ( msg == "\0" ) {
3119+ cur = app . createElement ( "p" )
3120+ cur_text = ""
3121+ cur_padding = 1
3122+ main . append ( app . createElement ( "br" ) , cur )
3123+ } else if ( msg == "\n" ) {
3124+ cur = app . createElement ( "p" )
3125+ cur_text = ""
3126+ cur_padding = 1
3127+ main . append ( cur )
3128+ } else if ( msg == "\b" ) {
3129+ cur_text += "<strong>"
3130+ } else if ( msg == "\r" ) {
3131+ cur_text += "</strong>"
3132+ } else {
3133+ if ( msg == "\t" ) {
3134+ cur . setStyle ( "padding-left" , ( ( cur_padding ++ ) * 24 ) + "px" )
3135+ msg = ""
3136+ }
3137+ cur_text += msg
3138+ cur . setHTML ( cur_text )
3139+ }
3140+ } , ( i - remove_index ) * 50 )
3141+ }
3142+ }
3143+ let messages = [
3144+ "您好!您的节点的基础报告已经出来啦!\0" ,
3145+ "这是基于小时数据\b数据量\r的统计:" ,
3146+ `\t时间:${ data . hour . bytes . time } ` ,
3147+ `\t数据量:\b${ this . _format_bytes ( data . hour . bytes . cache_bytes + data . hour . bytes . bytes ) } \r` ,
3148+ `\t下载次数:\b${ this . _format_number_unit ( data . hour . bytes . cache_hits + data . hour . bytes . hits ) } \r` ,
3149+ "而这是基于\b下载次数\r的统计:" ,
3150+ `\t时间:${ data . hour . hit . time } ` ,
3151+ `\t数据量:\b${ this . _format_bytes ( data . hour . hit . cache_bytes + data . hour . hit . bytes ) } \r` ,
3152+ `\t下载次数:\b${ this . _format_number_unit ( data . hour . hit . cache_hits + data . hour . hit . hits ) } \r` ,
3153+ "\0" ,
3154+ "这是基于日期数据\b数据量\r的统计:" ,
3155+ `\t时间:${ data . day . bytes . time } ` ,
3156+ `\t数据量:\b${ this . _format_bytes ( data . day . bytes . cache_bytes + data . day . bytes . bytes ) } \r` ,
3157+ `\t下载次数:\b${ this . _format_number_unit ( data . day . bytes . cache_hits + data . day . bytes . hits ) } \r` ,
3158+ "而这是基于\b下载次数\r的统计:" ,
3159+ `\t时间:${ data . day . hit . time } ` ,
3160+ `\t数据量:\b${ this . _format_bytes ( data . day . hit . cache_bytes + data . day . hit . bytes ) } \r` ,
3161+ `\t下载次数:\b${ this . _format_number_unit ( data . day . hit . cache_hits + data . day . hit . hits ) } \r` ,
3162+ "\0" ,
3163+ `已提供了 \b${ this . _format_number_unit ( data . total . cache_hits + data . total . hits ) } \r 次下载,\b${ this . _format_bytes ( data . total . cache_bytes + data . total . bytes ) } \r 下载数据量`
3164+ ]
3165+ print ( messages . reduce ( ( l , c ) => l + c + "\n" , "" ) )
3166+ modal . body ( main )
3167+ $progress . set ( 100 )
3168+ } )
28703169 } )
28713170 this . summary_container = app . createElement ( "div" ) . append (
28723171 this . summary
@@ -3103,7 +3402,29 @@ app.$Menu.add("dashboard", new class {
31033402 app . createElement ( "div" ) . class ( "title" , "flex-space-between" ) . append (
31043403 app . createElement ( "p" ) . class ( "title-color" ) . setI18N ( "dashboard.useragents" ) ,
31053404 app . createElement ( "button" ) . class ( "click-text" ) . setI18N ( "see.more" ) . event ( "click" , ( ) => {
3106- modal . open ( )
3405+ modal . open ( ) . title ( "客户端统计" )
3406+ var rank = app . createElement ( "div" ) . class ( "border-background" ) . setStyle ( "padding-top" , "8px" ) . setStyle ( "padding-bottom" , "8px" )
3407+ var data = [ ] ;
3408+ for ( const key in this . geo_stats != null && this . geo_stats . useragents != null ? this . geo_stats . useragents : { } ) {
3409+ data . push ( {
3410+ label : key ,
3411+ value : this . geo_stats . useragents [ key ]
3412+ } )
3413+ }
3414+ data = data . sort ( ( a , b ) => b . value - a . value )
3415+ for ( var index in data ) {
3416+ let value = data [ index ]
3417+ rank . append (
3418+ app . createElement ( "div" ) . class ( "flex" , "flex-space-between" , "flex-aligns-center" ) . style ( "margin-top: 8px; margin-bottom: 8px" ) . append (
3419+ app . createElement ( "div" ) . class ( "flex" , "flex-aligns-center" ) . append (
3420+ app . createElement ( "div" ) . class ( "rank-circle" ) . style ( `background-color: var(--echarts-color-${ index % 5 } ); ` ) ,
3421+ app . createElement ( "span" ) . class ( "title-color" ) . setText ( value . label )
3422+ ) ,
3423+ app . createElement ( "span" ) . style ( "font-weight: bold" ) . setText ( value . value )
3424+ )
3425+ )
3426+ }
3427+ modal . body ( rank )
31073428 } )
31083429 ) ,
31093430 app . createFlex ( true ) . minWidth ( 512 ) . childWidths ( 30 , 70 ) . append (
0 commit comments