front_generator: нормальные отступы для всех включаемых файлов, добавление страницы с логами для TDMA-терминала

This commit is contained in:
2025-09-16 18:52:16 +03:00
parent 483c174cd5
commit fa7be880a7
21 changed files with 1013 additions and 923 deletions

View File

@@ -133,7 +133,8 @@
"tabs": [
{"name": "monitoring", "desc": "Мониторинг"},
{"name": "setup", "desc": "Настройки"},
{"name": "admin", "desc": "Администрирование"}
{"name": "admin", "desc": "Администрирование"},
{"name": "logs", "desc": "Журнал"}
]
},
"scpc": {

View File

@@ -215,3 +215,4 @@
}
}
},

View File

@@ -1,7 +1,7 @@
{% from 'common/widgets.j2' import build_widget %}
<div class="tabs-body-item" v-if="activeTab === 'admin' && settingFetchComplete">
{% if 'network' in params %}
{% for w in params['network'] %}{{ build_widget('network', w) | indent(12, true) }}{% endfor %}
{% for w in params['network'] %}{{ build_widget('network', w) | indent(4, true) }}{% endfor %}
{% endif %}
{% raw %}
<h2>Система</h2>
@@ -50,3 +50,4 @@
{% endif %}
</div>
</div>

View File

@@ -0,0 +1,7 @@
paramLogs: {
submitClearLogs: false,
submitUpdateLogs: false,
data: "",
level: ""
},

View File

@@ -0,0 +1,12 @@
logsUpdate() {
if (this.paramLogs.submitUpdateLogs) { return }
this.paramLogs.submitUpdateLogs = true
fetch(`/api/get/manager.log?preview=1`, {method: 'GET', credentials: 'same-origin' })
.then(async (resp) => {
this.paramLogs.data = await resp.text()
})
.catch((reason) => { this.paramLogs.data = `Ошибка при чтении логов: ${reason}` })
.finally(() => { this.paramLogs.submitUpdateLogs = false })
},

View File

@@ -0,0 +1,17 @@
{% from 'common/widgets.j2' import build_widget %}
<div class="tabs-body-item" v-if="activeTab === 'logs'">
<h2>Журнал <code>manager</code></h2>
<div class="settings-set-container">
{{ build_widget('logs', {
"widget": "select", "label": "Фильтрация лога (отображение)", "name": "level",
"values": [{"label": "Без фильтрации", "value": "''"}, {"label": "Информация", "value": "'info'"}, {"label": "Предупреждение", "value": "'warning'"}, {"label": "Ошибка", "value": "'error'"}, {"label": "Фатальная ошибка", "value": "'fatal'"}]
}) | indent(8, true) }}
<button class="action-button" @click="logsUpdate()">Обновить (последние 1000 строк) <span class="submit-spinner" v-show="paramLogs.submitUpdateLogs"></span></button></button>
<a href="/api/get/manager.log" class="action-button" download>Скачать все</a>
<pre style="overflow-x: auto">{{ '{{ paramLogs.data }}' }}</pre>
<div><button class="action-button" v-if="paramLogs.data !== ''" @click="logsUpdate()">Обновить (последние 1000 строк) <span class="submit-spinner" v-show="paramLogs.submitUpdateLogs"></span></button></div>
</div>
<div class="settings-set-container statistics-container">
<div><button class="dangerous-button" @click="logsClear()">Очистить логи <span class="submit-spinner" v-show="paramLogs.submitClearLogs"></span></button></div>
</div>
</div>

View File

@@ -41,10 +41,8 @@
},
{% endif %}
statDevice: { // температурные датчики
adrv: 0, zynq: 0, fpga: 0
{% if modem == 'tdma' %},
upgradeStatus: "", upgradePercent: 0, upgradeImage: ""
{% endif %}
adrv: 0, zynq: 0, fpga: 0{% if modem == 'tdma' %}, upgradeStatus: "", upgradePercent: 0, upgradeImage: ""{% endif %}
},
statOs: {uptime: '?', load1: '?', load5: '?', load15: '?', totalram: '?', freeram: '?'},

View File

@@ -1,5 +1,4 @@
{% raw %}
<div class="tabs-body-item tabs-item-flex-container" v-if="activeTab === 'monitoring'">
{% raw %}<div class="tabs-body-item tabs-item-flex-container" v-if="activeTab === 'monitoring'">
<div class="settings-set-container statistics-container">
<h2>Статистика приема</h2>
<table>

View File

@@ -6,3 +6,4 @@
rt3: [],
cd: [],
},

View File

@@ -102,6 +102,6 @@
<button class="action-button" @click="settingsSubmitQoS()">Применить <span class="submit-spinner" v-show="submitStatusQos"></span></button>
{% endraw %}{% if 'tcpaccel' in params %}
{% for w in params['tcpaccel'] %}{{ build_widget('tcpaccel', w) | indent(12, true) }}{% endfor %}
{% for w in params['tcpaccel'] %}{{ build_widget('tcpaccel', w) | indent(4, true) }}{% endfor %}
{% endif %}
</div>

View File

@@ -2,7 +2,7 @@
<div class="tabs-body-item" v-if="activeTab === 'setup' && settingFetchComplete">
{% for cat in ['rxtx', 'dpdi', 'buclnb'] %}
{% if cat in params %}
{% for w in params[cat] %}{{ build_widget(cat, w) | indent(12, true) }}{% endfor %}
{% for w in params[cat] %}{{ build_widget(cat, w) | indent(4, true) }}{% endfor %}
{% endif %}
{% endfor %}
</div>

View File

@@ -1,5 +1,18 @@
<!DOCTYPE html>
<html lang="en">
{% macro include_macro(file) %}
// ========== include from '{{ file }}'
{% include file %}
// ========== include end from '{{ file }}'
{% endmacro %}
{% macro include_macro_no_comment(file) %}
{% include file %}
{% endmacro %}
{% macro include_macro_ignore_missing(file) %}
// ========== include from '{{ file }}'
{% include file ignore missing %}
// ========== include end from '{{ file }}'
{% endmacro %}
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -53,7 +66,7 @@
</div>
</header>
<div id="content">
{% for tab in header_tabs %}{% include 'common/' ~ tab.name ~ '.html.j2' %}{% endfor %}
{% for tab in header_tabs %}{{ include_macro_no_comment('common/' ~ tab.name ~ '.html.j2') | indent(8, true) }}{% endfor %}
{% raw %}
<p>Последнее обновление статистики: {{ lastUpdateTime }}</p>
</div>
@@ -108,15 +121,9 @@
cesPasswordValue: '',
{% endif %}
// ========== include from 'common/all-params-data.js.j2'
{% include 'common/all-params-data.js.j2' %}
// ========== include end from 'common/all-params-data.js.j2'
{{ include_macro('common/all-params-data.js.j2') | indent(16, true) }}
{% 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' }}'
{{ include_macro_ignore_missing('common/' ~ tab.name ~ '-data.js.j2') | indent(16, true) }}
{% endfor %}
uploadFw: {
progress: null,
@@ -183,15 +190,9 @@
return toLocaleStringWithSpaces(result)
},
// ========== include from 'common/all-params-methods.js.j2'
{% include 'common/all-params-methods.js.j2' %}
// ========== include end from 'common/all-params-methods.js.j2'
{{ include_macro('common/all-params-methods.js.j2') | indent(12, true) }}
{% 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' }}'
{{ include_macro_ignore_missing('common/' ~ tab.name ~ '-methods.js.j2') | indent(12, true) }}
{% endfor %}
performUpdateSettings() {

View File

@@ -26,5 +26,9 @@
#define API_OBJECT_BUCLNB_SETTINGS_ENABLE
#endif
#if defined(MODEM_IS_TDMA)
#define API_OBJECT_MANAGER_LOGS_ENABLE
#endif
#endif //API_DRIVER_STRICTS_ENABLE_H

View File

@@ -52,7 +52,6 @@
</div>
</header>
<div id="content">
<div class="tabs-body-item tabs-item-flex-container" v-if="activeTab === 'monitoring'">
<div class="settings-set-container statistics-container">
<h2>Статистика приема</h2>
@@ -549,6 +548,7 @@
<button class="dangerous-button" v-show="uploadFw.sha256 !== null" @click="settingsPerformFirmwareUpgrade()">Обновить встроенное ПО<span class="submit-spinner" v-show="submitStatus.firmwareUpgrade"></span></button>
</div>
</div>
<p>Последнее обновление статистики: {{ lastUpdateTime }}</p>
</div>
</div>
@@ -710,7 +710,8 @@
rt2: [],
rt3: [],
cd: [],
}, // ========== include end from 'common/qos-data.js.j2'
},
// ========== include end from 'common/qos-data.js.j2'
// ========== include from 'common/admin-data.js.j2'
// ========== include end from 'common/admin-data.js.j2'
@@ -1492,7 +1493,8 @@
downloadAsFile(JSON.stringify(jres["settings"], null, 4), "backup-" + this.about.firmwareVersion + "-" + this.about.modemSn + ".json")
}
}
}, // ========== include end from 'common/admin-methods.js.j2'
},
// ========== include end from 'common/admin-methods.js.j2'
performUpdateSettings() {

View File

@@ -51,7 +51,6 @@
</div>
</header>
<div id="content">
<div class="tabs-body-item tabs-item-flex-container" v-if="activeTab === 'monitoring'">
<div class="settings-set-container statistics-container">
<h2>Статистика приема</h2>
@@ -310,6 +309,7 @@
<button class="dangerous-button" v-show="uploadFw.sha256 !== null" @click="settingsPerformFirmwareUpgrade()">Обновить встроенное ПО<span class="submit-spinner" v-show="submitStatus.firmwareUpgrade"></span></button>
</div>
</div>
<p>Последнее обновление статистики: {{ lastUpdateTime }}</p>
</div>
</div>
@@ -903,7 +903,8 @@
downloadAsFile(JSON.stringify(jres["settings"], null, 4), "backup-" + this.about.firmwareVersion + "-" + this.about.modemSn + ".json")
}
}
}, // ========== include end from 'common/admin-methods.js.j2'
},
// ========== include end from 'common/admin-methods.js.j2'
performUpdateSettings() {

View File

@@ -47,11 +47,11 @@
<a href="#monitoring" class="tabs-btn" @click="activeTab = 'monitoring'" :class="{ active: activeTab === 'monitoring' }">Мониторинг</a>
<a href="#setup" class="tabs-btn" @click="activeTab = 'setup'" :class="{ active: activeTab === 'setup' }">Настройки</a>
<a href="#admin" class="tabs-btn" @click="activeTab = 'admin'" :class="{ active: activeTab === 'admin' }">Администрирование</a>
<a href="#logs" class="tabs-btn" @click="activeTab = 'logs'" :class="{ active: activeTab === 'logs' }">Журнал</a>
<a href="/logout" class="tabs-btn">Выход</a>
</div>
</header>
<div id="content">
<div class="tabs-body-item tabs-item-flex-container" v-if="activeTab === 'monitoring'">
<div class="settings-set-container statistics-container">
<h2>Статистика приема</h2>
@@ -297,12 +297,35 @@
<button class="dangerous-button" v-show="statDevice.upgradePercent >= 100" @click="settingsPerformFirmwareUpgradeOta()">Обновить встроенное ПО<span class="submit-spinner" v-show="submitStatus.firmwareUpgradeOta"></span></button>
</div>
</div>
<div class="tabs-body-item" v-if="activeTab === 'logs'">
<h2>Журнал <code>manager</code></h2>
<div class="settings-set-container">
<label>
<span>Фильтрация лога (отображение)</span>
<select v-model="paramLogs.level">
<option :value="''">Без фильтрации</option>
<option :value="'info'">Информация</option>
<option :value="'warning'">Предупреждение</option>
<option :value="'error'">Ошибка</option>
<option :value="'fatal'">Фатальная ошибка</option>
</select>
</label>
<button class="action-button" @click="logsUpdate()">Обновить (последние 1000 строк) <span class="submit-spinner" v-show="paramLogs.submitUpdateLogs"></span></button></button>
<a href="/api/get/manager.log" class="action-button" download>Скачать все</a>
<pre style="overflow-x: auto">{{ paramLogs.data }}</pre>
<div><button class="action-button" v-if="paramLogs.data !== ''" @click="logsUpdate()">Обновить (последние 1000 строк) <span class="submit-spinner" v-show="paramLogs.submitUpdateLogs"></span></button></div>
</div>
<div class="settings-set-container statistics-container">
<div><button class="dangerous-button" @click="logsClear()">Очистить логи <span class="submit-spinner" v-show="paramLogs.submitClearLogs"></span></button></div>
</div>
</div>
<p>Последнее обновление статистики: {{ lastUpdateTime }}</p>
</div>
</div>
<script src="/js/vue.js?v=3.5.13"></script>
<script>
const availableTabs = ['monitoring', 'setup', 'admin']
const availableTabs = ['monitoring', 'setup', 'admin', 'logs']
// для обновления высоты хидера
function updateHeaderHeight() { const header = document.querySelector('header'); document.body.style.setProperty('--header-height', `${header.offsetHeight}px`); }
@@ -414,9 +437,7 @@
modcod: '?', speedOnTxKbit: '?', speedOnIifKbit: '?', centerFreq: '?', symSpeed: '?'
},
statDevice: { // температурные датчики
adrv: 0, zynq: 0, fpga: 0
,
upgradeStatus: "", upgradePercent: 0, upgradeImage: ""
adrv: 0, zynq: 0, fpga: 0, upgradeStatus: "", upgradePercent: 0, upgradeImage: ""
},
statOs: {uptime: '?', load1: '?', load5: '?', load15: '?', totalram: '?', freeram: '?'},
// ========== include end from 'common/monitoring-data.js.j2'
@@ -427,6 +448,15 @@
// ========== include from 'common/admin-data.js.j2'
// ========== include end from 'common/admin-data.js.j2'
// ========== include from 'common/logs-data.js.j2'
paramLogs: {
submitClearLogs: false,
submitUpdateLogs: false,
data: "",
level: ""
},
// ========== include end from 'common/logs-data.js.j2'
uploadFw: {
progress: null,
filename: null,
@@ -918,7 +948,22 @@
downloadAsFile(JSON.stringify(jres["settings"], null, 4), "backup-" + this.about.firmwareVersion + "-" + this.about.modemSn + ".json")
}
}
}, // ========== include end from 'common/admin-methods.js.j2'
},
// ========== include end from 'common/admin-methods.js.j2'
// ========== include from 'common/logs-methods.js.j2'
logsUpdate() {
if (this.paramLogs.submitUpdateLogs) { return }
this.paramLogs.submitUpdateLogs = true
fetch(`/api/get/manager.log?preview=1`, {method: 'GET', credentials: 'same-origin' })
.then(async (resp) => {
this.paramLogs.data = await resp.text()
})
.catch((reason) => { this.paramLogs.data = `Ошибка при чтении логов: ${reason}` })
.finally(() => { this.paramLogs.submitUpdateLogs = false })
},
// ========== include end from 'common/logs-methods.js.j2'
performUpdateSettings() {