238 lines
9.8 KiB
HTML
238 lines
9.8 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>{{ modem_name }}</title>
|
||
<link rel="stylesheet" type="text/css" href="/style.css">
|
||
<link rel="stylesheet" type="text/css" href="/fields.css">
|
||
<style>{% raw %}
|
||
header {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
z-index: 10;
|
||
background: var(--bg-selected);
|
||
}
|
||
|
||
body { /* значение по-умолчанию */ --header-height: 60px; }
|
||
|
||
#content {
|
||
padding-top: var(--header-height);
|
||
}
|
||
|
||
.l3-proto-label {
|
||
margin: 0 0 0 0.5em;
|
||
}
|
||
.l3-proto-label > * {
|
||
display: inline-block;
|
||
}
|
||
.l3-proto-label input[type=checkbox] {
|
||
width: auto;
|
||
}
|
||
{% endraw %}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<div id="app" hidden>
|
||
<header>{% raw %}
|
||
<span class="nav-bar-element">Прием: <span :class="{ indicator_bad: statRx.state === false, indicator_good: statRx.state === true, indicator: true }"></span></span>
|
||
<span class="nav-bar-element">Передача: <span :class="{ indicator_good: statTx.state === true, indicator: true }"></span></span>
|
||
<span class="nav-bar-element">Тест: <span :class="{ indicator_good: testState, indicator: true }"></span></span>
|
||
<!-- Последнее обновление: {{ lastUpdateTime }}-->
|
||
<span :class="{ value_bad: initState !== 'Успешная инициализация системы' }">{{ initState }}</span>
|
||
{% endraw %}
|
||
<div class="tabs-header">
|
||
<span style="font-weight:bold">{{ modem_name }}</span>
|
||
{% for tab in header_tabs %}
|
||
<a href="#{{ tab.name }}" class="tabs-btn" @click="activeTab = '{{ tab.name }}'" :class="{{ '{' }} active: activeTab === '{{ tab.name }}' {{ '}' }}">{{ tab.desc }}</a>
|
||
{% endfor %}
|
||
<a href="/logout" class="tabs-btn">Выход</a>
|
||
</div>
|
||
</header>
|
||
<div id="content">
|
||
{% for tab in header_tabs %}{% include 'common/' ~ tab.name ~ '.html.j2' %}{% endfor %}
|
||
{% raw %}
|
||
<p>Последнее обновление статистики: {{ lastUpdateTime }}</p>
|
||
</div>
|
||
{% endraw %}
|
||
</div>
|
||
<script src="/js/vue.js?v=3.5.13"></script>
|
||
<script>
|
||
const availableTabs = ['{{ tab_names_array | join("', '") }}']
|
||
|
||
// для обновления высоты хидера
|
||
function updateHeaderHeight() { const header = document.querySelector('header'); document.body.style.setProperty('--header-height', `${header.offsetHeight}px`); }
|
||
window.addEventListener('load', updateHeaderHeight); window.addEventListener('resize', updateHeaderHeight);
|
||
|
||
function getCurrentTab() {
|
||
const sl = window.location.hash.slice(1)
|
||
if (availableTabs.indexOf(sl) >= 0) {
|
||
return sl
|
||
}
|
||
return availableTabs[0]
|
||
}
|
||
|
||
const app = Vue.createApp({
|
||
data() {
|
||
return {
|
||
// false - означает что статистика не отправляется, true - отправляется
|
||
submitStatus: {
|
||
{% for pg in paramGroupsList %}
|
||
{{ pg }}: false,
|
||
{% endfor %}
|
||
firmwareUpload: false,
|
||
firmwareUpgrade: false,
|
||
// когда модем перезагружается, тут должен быть счетчик. Направление счета - к нулю
|
||
modemReboot: null
|
||
},
|
||
|
||
// ========== include from 'common/all-params-data.js.j2'
|
||
{% include 'common/all-params-data.js.j2' %}
|
||
// ========== include end from 'common/all-params-data.js.j2'
|
||
|
||
{% for tab in header_tabs %}
|
||
// ========== include from '{{ 'common/' ~ tab.name ~ '-data.js.j2' }}'
|
||
{% include 'common/' ~ tab.name ~ '-data.js.j2' ignore missing %}
|
||
// ========== include end from '{{ 'common/' ~ tab.name ~ '-data.js.j2' }}'
|
||
|
||
{% endfor %}
|
||
uploadFw: {
|
||
progress: null,
|
||
filename: null,
|
||
sha256: null
|
||
},
|
||
|
||
// эти "настройки" - read only
|
||
about: {
|
||
firmwareVersion: '?',
|
||
modemUid: '?',
|
||
modemSn: '?',
|
||
macManagement: '?',
|
||
macData: '?',
|
||
},
|
||
|
||
testState: false,
|
||
initState: '',
|
||
lastUpdateTime: new Date(),
|
||
activeTab: getCurrentTab(),
|
||
settingFetchComplete: false,
|
||
}
|
||
},
|
||
methods: {
|
||
correctModcodSpeed(modulation, speed) {
|
||
const mod = modulation.toLowerCase()
|
||
const available = {
|
||
"qpsk": ['1/4', '1/3', '2/5', '1/2', '3/5', '2/3', '3/4', '4/5', '5/6', '8/9', '9/10'],
|
||
"8psk": ['2/3', '3/4', '5/6', '8/9', '9/10'],
|
||
"16apsk": ['2/3', '3/4', '4/5', '5/6', '8/9', '9/10'],
|
||
"32apsk": ['3/4', '4/5', '5/6', '8/9', '9/10']
|
||
}
|
||
if (mod in available) {
|
||
if (available[mod].indexOf(speed) >= 0) {
|
||
return speed
|
||
}
|
||
return available[mod][0]
|
||
}
|
||
return ""
|
||
},
|
||
getAvailableModcods(modulation) {
|
||
// NOTE модкоды со скоростью хода 3/5 не работают
|
||
switch (modulation) {
|
||
case 'qpsk':
|
||
return ['1/4', '1/3', '2/5', '1/2', '3/5', '2/3', '3/4', '4/5', '5/6', '8/9', '9/10']
|
||
case '8psk':
|
||
return ['3/5', '2/3', '3/4', '5/6', '8/9', '9/10']
|
||
case '16apsk':
|
||
return ['2/3', '3/4', '4/5', '5/6', '8/9', '9/10']
|
||
case '32apsk':
|
||
return ['3/4', '4/5', '5/6', '8/9', '9/10']
|
||
default:
|
||
return []
|
||
}
|
||
},
|
||
inputFormatInt(src, validation) {
|
||
if (validation === null || validation === undefined) { validation = {} }
|
||
const rawVal = src.toString().replace(/[^0-9]/g, '')
|
||
let result = rawVal === '' ? 0 : parseInt(rawVal)
|
||
if ('min' in validation) { if (result <= validation['min']) { result = validation['min'] } }
|
||
if ('max' in validation) { if (result >= validation['max']) { result = validation['max'] } }
|
||
return result.toLocaleString()
|
||
},
|
||
|
||
// ========== include from 'common/all-params-methods.js.j2'
|
||
{% include 'common/all-params-methods.js.j2' %}
|
||
// ========== include end from 'common/all-params-methods.js.j2'
|
||
|
||
{% for tab in header_tabs %}
|
||
// ========== include from '{{ 'common/' ~ tab.name ~ '-methods.js.j2' }}'
|
||
{% include 'common/' ~ tab.name ~ '-methods.js.j2' ignore missing %}
|
||
// ========== include end from '{{ 'common/' ~ tab.name ~ '-methods.js.j2' }}'
|
||
|
||
{% endfor %}
|
||
|
||
performUpdateSettings() {
|
||
const doFetchSettings = async () => {
|
||
let d = await fetch("/api/get/settings")
|
||
let vals = await d.json()
|
||
this.settingFetchComplete = true
|
||
{% for pg in paramGroupsList %}
|
||
this.update{{ pg | capitalize }}Settings(vals)
|
||
{% endfor %}
|
||
{% if 'qos' in tab_names_array %}
|
||
this.updateQosSettings(vals)
|
||
{% endif %}
|
||
}
|
||
|
||
doFetchSettings().then(() => {})
|
||
}
|
||
},
|
||
mounted() {
|
||
const doFetchStatistics = async () => {
|
||
if (this.submitStatus.modemReboot !== null) {
|
||
this.initState = `Перезагрузка модема... Осталось ${this.submitStatus.modemReboot} сек`
|
||
this.submitStatus.modemReboot--
|
||
if (this.submitStatus.modemReboot <= 0) {
|
||
window.location.reload()
|
||
}
|
||
} else {
|
||
try {
|
||
let d = await fetch("/api/get/statistics", { credentials: 'same-origin' })
|
||
this.updateStatistics(await d.json())
|
||
} catch (e) {
|
||
this.initState = "Ошибка обновления статистики"
|
||
}
|
||
}
|
||
setTimeout(() => {
|
||
doFetchStatistics()
|
||
}, 1000)
|
||
}
|
||
|
||
const doFetchAbout = async () => {
|
||
try {
|
||
const fr = await fetch("/api/get/aboutFirmware")
|
||
const d = await fr.json()
|
||
this.about.firmwareVersion = d["fw.version"]
|
||
this.about.modemUid = d["fw.modemId"]
|
||
this.about.modemSn = d["fw.modemSn"]
|
||
this.about.macManagement = d["fw.macMang"]
|
||
this.about.macData = d["fw.macData"]
|
||
} catch (e) {
|
||
console.log('Ошибка загрузки версии ПО', e)
|
||
}
|
||
}
|
||
|
||
doFetchStatistics().then(() => {})
|
||
doFetchAbout().then(() => {})
|
||
|
||
this.performUpdateSettings()
|
||
|
||
document.getElementById("app").removeAttribute("hidden")
|
||
}
|
||
});
|
||
app.mount('#app')
|
||
</script>
|
||
</body>
|
||
</html> |