@ -1039,6 +1039,15 @@ HTML = """<!doctype html>
. netron - state { min - width : 0 ; color : #8e99a6; font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
. netron - panel { min - height : 420 px ; margin - top : 8 px ; overflow : hidden ; border : 1 px solid #2b3037; background: #fff; }
. netron - frame { display : block ; width : 100 % ; height : min ( 68 vh , 720 px ) ; border : 0 ; background : #fff; }
. netron - tab { height : 100 % ; min - height : 0 ; overflow : auto ; padding : 10 px ; }
. netron - page - panel { width : min ( 1400 px , 100 % ) ! important ; min - height : 100 % ; margin : 0 auto ; border : 1 px solid var ( - - ui - border ) ; background : var ( - - ui - surface ) ; }
. netron - page - section { min - height : 100 % ; padding : 16 px ; border : 0 ; }
. netron - page - head { display : flex ; align - items : end ; justify - content : space - between ; gap : 16 px ; flex - wrap : wrap ; }
. netron - page - head h2 { margin : 0 ; }
. netron - model - field { min - width : min ( 420 px , 100 % ) ; display : grid ; gap : 4 px ; color : var ( - - ui - muted ) ; font - size : 12 px ; }
. netron - model - field select { min - width : 0 ; height : 34 px ; border : 1 px solid var ( - - ui - border ) ; border - radius : var ( - - ui - radius ) ; background : var ( - - ui - input ) ; color : var ( - - ui - text ) ; padding : 0 10 px ; font : inherit ; }
. netron - page - section . netron - panel { min - height : calc ( 100 vh - 230 px ) ; }
. netron - page - section . netron - frame { height : min ( 74 vh , 860 px ) ; }
. theme - select { width : 112 px ; height : 28 px ; border : 1 px solid #2b3037; background: #101317; color: #dce3ea; padding: 0 5px; font: 11px Segoe UI, Arial, sans-serif; }
. control - form { display : grid ; grid - template - columns : 1 fr 1 fr ; align - items : start ; }
. settings - group { min - width : 0 ; margin : 0 ; padding : 10 px ; border : 0 ; border - bottom : 1 px solid #2b3037; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
@ -1212,7 +1221,7 @@ HTML = """<!doctype html>
. theme - select , . accent - select , . accent - custom { border - radius : 8 px ; transition : border - color .2 s ease , box - shadow .2 s ease , transform .2 s ease ; }
. theme - select : hover , . accent - select : hover , . accent - custom : hover { border - color : var ( - - ui - accent ) ! important ; transform : translateY ( - 1 px ) ; }
main { height : calc ( 100 vh - 52 px ) ; }
. stream - tab , . archive - tab , . settings - tab , . model - tab { padding : 10 px ; }
. stream - tab , . archive - tab , . settings - tab , . model - tab , . netron - tab { padding : 10 px ; }
. stage , . settings - panel , . model - panel , . archive - panel , . log - drawer , . player - box , . netron - panel { border - radius : var ( - - ui - radius ) ; box - shadow : var ( - - ui - shadow ) ; }
. stage { isolation : isolate ; }
. stage : : after { content : " " ; position : absolute ; inset : 0 ; pointer - events : none ; border - radius : inherit ; box - shadow : inset 0 0 0 1 px color - mix ( in srgb , var ( - - ui - accent ) 8 % , transparent ) ; }
@ -1537,6 +1546,7 @@ HTML = """<!doctype html>
< button class = " tab " type = " button " data - tab = " archive " > Архив < / button >
< button class = " tab " type = " button " data - tab = " settings " > Настройки < / button >
< button class = " tab " type = " button " data - tab = " model " > Сеть < / button >
< button class = " tab " type = " button " data - tab = " netron " > Netron < / button >
< / nav >
< div class = " appearance-module " >
< button id = " appearanceToggle " class = " appearance-trigger " type = " button " aria - expanded = " false " aria - controls = " appearancePanel " >
@ -1840,7 +1850,7 @@ HTML = """<!doctype html>
< aside id = " networkRestorePanel " class = " config-restore-panel network-restore-panel " hidden >
< span class = " config-restore-title " > Структура сети < / span >
< div class = " config-structure-create " >
< label > Шаблон < select id = " networkTemplateSelect " > < option value = " model " > Модель < / option > < option value = " model-params " > Параметры < / option > < option value = " netron " > Netron < / option > < / select > < / label >
< label > Шаблон < select id = " networkTemplateSelect " > < option value = " model " > Модель < / option > < option value = " model-params " > Параметры < / option > < / select > < / label >
< label > Название < input id = " networkBlockTitle " type = " text " maxlength = " 48 " placeholder = " Мой блок " > < / label >
< button id = " networkCreateBlock " type = " button " > создать блок < / button >
< / div >
@ -1876,8 +1886,22 @@ HTML = """<!doctype html>
< label > Макс . детекций < input id = " modelMaxDet " type = " number " min = " 1 " max = " 300 " step = " 1 " value = " 60 " > < / label >
< span class = " model-state model-wide " > Параметры применяются при следующем старте . < / span >
< / section >
< section class = " netron-section network-visual-card network-block " data - section = " netron " >
< div class = " network-summary " > Визуализация сети < / div >
< / div >
< / div >
< / section >
< / div >
< div id = " netronTab " class = " tab-page netron-tab " hidden >
< section class = " model-panel netron-page-panel " >
< div class = " netron-section netron-page-section " >
< div class = " netron-page-head " >
< div >
< h2 > Netron < / h2 >
< span class = " netron-state " > Архитектура модели до инференса < / span >
< / div >
< label class = " netron-model-field " > Модель
< select id = " netronModelSelect " > < option value = " " > загрузка списка . . . < / option > < / select >
< / label >
< / div >
< div class = " netron-toolbar " >
< button id = " modelNetron " class = " command primary " type = " button " > Показать в Netron < / button >
< span id = " netronState " class = " netron-state " > граф Netron не загружен < / span >
@ -1885,8 +1909,6 @@ HTML = """<!doctype html>
< div id = " netronPanel " class = " netron-panel " hidden >
< iframe id = " netronFrame " class = " netron-frame " title = " Визуализация архитектуры сети в Netron " loading = " lazy " sandbox = " allow-scripts allow-same-origin " > < / iframe >
< / div >
< / section >
< / div >
< / div >
< / section >
< / div >
@ -3674,23 +3696,23 @@ HTML = """<!doctype html>
}
async function loadModels ( ) {
const data = await fetch ( ' /api/models ' , { cache : ' no-store ' } ) . then ( r = > r . json ( ) ) ;
const select = $ ( ' modelSelect ' ) ;
select . innerHTML = ' ' ;
for ( const model of data . models | | [ ] ) {
const select s = [ $ ( ' modelSelect ' ) , $ ( ' netronModelSelect ' ) ] . filter ( Boolean ) ;
select s. forEach ( select = > { select . innerHTML = ' ' ; } ) ;
for ( const model of data . models | | [ ] ) selects . forEach ( select = > {
const option = document . createElement ( ' option ' ) ;
option . value = model . path ;
option . textContent = ` $ { model . name } · $ { mb ( model . size ) } ` ;
select . appendChild ( option ) ;
}
} ) ;
const selected = data . selected | | data . default | | ' ' ;
if ( ! select . options . length ) {
select . innerHTML = ' <option value= " " >модели .pt не найдены</option> ' ;
} else if ( selected ) {
select . value = selected ;
}
if ( select . value ) {
setValue ( ' modelPath ' , s elect. value ) ;
setText ( ' modelState ' , ` $ { s elect. selectedOptions [ 0 ] ? . textContent | | ' модель выбрана ' } ` ) ;
selects . forEach ( select = > {
if ( ! select . options . length ) select . innerHTML = ' <option value= " " >модели .pt не найдены</option> ' ;
else if ( selected ) select . value = selected ;
} ) ;
const modelSelect = $ ( ' modelSelect ' ) ;
if ( modelSelect? . value ) {
setValue ( ' modelPath ' , modelS elect. value ) ;
setText ( ' modelState ' , ` $ { modelS elect. selectedOptions [ 0 ] ? . textContent | | ' модель выбрана ' } ` ) ;
}
}
function resetNetron ( ) {
@ -3699,7 +3721,7 @@ HTML = """<!doctype html>
setText ( ' netronState ' , ' граф Netron не загружен ' ) ;
}
async function openNetron ( ) {
const path = $ ( ' modelSelect' ) . value | | $ ( ' modelPath ' ) . value ;
const path = $ ( ' netronModelSelect' ) ? . value | | $ ( ' modelSelect' ) . value | | $ ( ' modelPath ' ) . value ;
if ( ! path ) throw new Error ( ' выберите файл модели .pt ' ) ;
setText ( ' netronState ' , ' запуск Netron... ' ) ;
const response = await fetch ( ' /api/model/netron?path= ' + enc ( path ) , { cache : ' no-store ' } ) ;
@ -4078,12 +4100,13 @@ HTML = """<!doctype html>
$ ( ' playerOverlay ' ) . hidden = true ;
}
function switchTab ( name , updateHash = true ) {
if ( ! [ ' stream ' , ' archive ' , ' settings ' , ' model ' ]. includes ( name ) ) name = ' stream ' ;
if ( ! [ ' stream ' , ' archive ' , ' settings ' , ' model ' , ' netron ' ]. includes ( name ) ) name = ' stream ' ;
document . querySelectorAll ( ' .tab ' ) . forEach ( btn = > btn . classList . toggle ( ' active ' , btn . dataset . tab == = name ) ) ;
$ ( ' streamTab ' ) . hidden = name != = ' stream ' ;
$ ( ' archiveTab ' ) . hidden = name != = ' archive ' ;
$ ( ' settingsTab ' ) . hidden = name != = ' settings ' ;
$ ( ' modelTab ' ) . hidden = name != = ' model ' ;
$ ( ' netronTab ' ) . hidden = name != = ' netron ' ;
if ( name == = ' settings ' & & typeof applyStoredConfigLayout == = ' function ' ) requestAnimationFrame ( applyStoredConfigLayout ) ;
if ( name == = ' model ' & & typeof applyNetworkLayout == = ' function ' ) requestAnimationFrame ( applyNetworkLayout ) ;
if ( name == = ' archive ' ) loadArchive ( ) ;
@ -4320,6 +4343,14 @@ HTML = """<!doctype html>
$ ( ' decorIntensity ' ) . addEventListener ( ' input ' , e = > applyAppearanceSetting ( ' decor ' , e . target . value ) ) ;
document . querySelectorAll ( ' [data-setting] ' ) . forEach ( button = > button . addEventListener ( ' click ' , ( ) = > applyAppearanceSetting ( button . dataset . setting , button . dataset . value ) ) ) ;
$ ( ' modelSelect ' ) . addEventListener ( ' change ' , e = > {
setValue ( ' modelPath ' , e . target . value ) ;
setValue ( ' netronModelSelect ' , e . target . value ) ;
setText ( ' modelState ' , e . target . selectedOptions [ 0 ] ? . textContent | | ' модель выбрана ' ) ;
resetNetron ( ) ;
controlDirty = true ;
} ) ;
$ ( ' netronModelSelect ' ) . addEventListener ( ' change ' , e = > {
setValue ( ' modelSelect ' , e . target . value ) ;
setValue ( ' modelPath ' , e . target . value ) ;
setText ( ' modelState ' , e . target . selectedOptions [ 0 ] ? . textContent | | ' модель выбрана ' ) ;
resetNetron ( ) ;