прототип QoS

This commit is contained in:
Vladislav Ostapov 2024-11-08 17:11:14 +03:00
parent 16b9776bfd
commit d1ad7baad1
3 changed files with 100 additions and 22 deletions

View File

@ -113,6 +113,29 @@ select * {
background: var(--bg-selected); background: var(--bg-selected);
} }
.settings-set-container details summary {
display: flex;
justify-content: space-between;
}
.dangerous-button, .action-button {
border: solid 1px var(--text-color2);
border-radius: 0.5em;
padding: 0.3em;
margin: 0.2em;
}
summary .dangerous-button, summary .action-button {
margin: 0;
}
.dangerous-button {
background: var(--bg-danger);
}
.action-button {
background: var(--brand-bg);
}
/*********************** Стили для красивых 'switch' ***********************/ /*********************** Стили для красивых 'switch' ***********************/
.toggle-input { .toggle-input {

View File

@ -43,7 +43,7 @@
</div> </div>
</header> </header>
<div id="content"> <div id="content">
<div class="tabs-body-item tabs-item-flex-container" v-show="activeTab === 'monitoring'"> <div class="tabs-body-item tabs-item-flex-container" v-if="activeTab === 'monitoring'">
<div class="settings-set-container"> <div class="settings-set-container">
<h2>Статистика приема</h2> <h2>Статистика приема</h2>
<table> <table>
@ -112,7 +112,7 @@
</table> </table>
</div> </div>
</div> </div>
<div class="tabs-body-item" v-show="activeTab === 'setup' && settingFetchComplete"> <div class="tabs-body-item" v-if="activeTab === 'setup' && settingFetchComplete">
<h2>Настройки приема/передачи</h2> <h2>Настройки приема/передачи</h2>
<div class="settings-set-container"> <div class="settings-set-container">
<label> <label>
@ -424,7 +424,7 @@
</div> </div>
<button type="submit">Сохранить</button> <button type="submit">Сохранить</button>
</div> </div>
<div class="tabs-body-item" v-show="activeTab === 'qos'"> <div class="tabs-body-item" v-if="activeTab === 'qos'">
<h2>Настройки QoS</h2> <h2>Настройки QoS</h2>
<div class="settings-set-container"> <div class="settings-set-container">
<label> <label>
@ -432,9 +432,8 @@
<span class="toggle-input"><input type="checkbox" v-model="qos.en" /><span class="slider"></span></span> <span class="toggle-input"><input type="checkbox" v-model="qos.en" /><span class="slider"></span></span>
</label> </label>
</div> </div>
<h3>Классы CD</h3> <h3>Классы CD</h3>
<button @click="qosAddClass('cd')">Добавить класс CD</button> <button class="action-button" @click="qosAddClass('cd')">Добавить класс CD</button>
<details v-for="(rule, index) in qos.cd" :key="index" class="settings-set-container"> <details v-for="(rule, index) in qos.cd" :key="index" class="settings-set-container">
<summary >#{{ index }} CIR={{ rule.cir }}кбит, PIR={{ rule.pir }}кбит {{ rule.description }}</summary> <summary >#{{ index }} CIR={{ rule.cir }}кбит, PIR={{ rule.pir }}кбит {{ rule.description }}</summary>
<label> <label>
@ -451,45 +450,46 @@
</label> </label>
<h3>Фильтры ({{ rule.filters.length }})</h3> <h3>Фильтры ({{ rule.filters.length }})</h3>
<button @click="qosClassAddRule('cd', index)">Добавить правило</button> <div>
<details v-for="filter in rule.filters" class="settings-set-container"> <button class="action-button" @click="qosClassAddRule('cd', index)">Добавить правило</button>
<!-- :key="filterIndex"--> </div>
<!-- <summary>Правило #{{ filterIndex }}</summary>--> <details v-for="(filter, filterIndex) in rule.filters" :key="filterIndex" class="settings-set-container">
<summary><span>#{{ filterIndex }} {{ qosGenerateRuleDescription(filter) }}</span> <button class="dangerous-button" @click="qosDelFilter('cd', index, filterIndex)">Del</button></summary>
<label> <label>
<span>vlan</span> <span>VLAN ID</span>
<input v-model="filter.vlan" type="text"> <input v-model="filter.vlan" type="text">
</label> </label>
<label> <label>
<span>proto</span> <span>Протокол L3</span>
<input v-model="filter.proto" type="text"> <input v-model="filter.proto" type="text">
</label> </label>
<label> <label>
<span>sport</span> <span>Порт источника</span>
<input v-model="filter.sport" type="text"> <input v-model="filter.sport" type="text">
</label> </label>
<label> <label>
<span>dport</span> <span>Порт назначения</span>
<input v-model="filter.dport" type="text"> <input v-model="filter.dport" type="text">
</label> </label>
<label> <label>
<span>ip_src</span> <span>IP источника</span>
<input v-model="filter.ip_src" type="text"> <input v-model="filter.ip_src" type="text">
</label> </label>
<label> <label>
<span>ip_dest</span> <span>IP назначения</span>
<input v-model="filter.ip_dest" type="text"> <input v-model="filter.ip_dest" type="text">
</label> </label>
<label> <label>
<span>dscp</span> <span>Метка IP.DSCP</span>
<input v-model="filter.dscp" type="text"> <input v-model="filter.dscp" type="text">
</label> </label>
</details> </details>
<button @click="qosDelClass('cd', index)">Del</button> <div>
<button class="dangerous-button" @click="qosDelClass('cd', index)">Удалить класс QoS</button>
</div>
</details> </details>
<button class="action-button">Применить</button>
<button>Применить</button>
<p> <p>
Эти настройки пока недоступны, но скоро разработчик это поправит. А пока купи разработчику банку <strike>пива</strike> колы) Эти настройки пока недоступны, но скоро разработчик это поправит. А пока купи разработчику банку <strike>пива</strike> колы)
@ -498,7 +498,7 @@
<source src="/vid/video_2024-11-06_15-49-35.mp4" type="video/mp4" /> <source src="/vid/video_2024-11-06_15-49-35.mp4" type="video/mp4" />
</video> </video>
</div> </div>
<div class="tabs-body-item" v-show="activeTab === 'admin'"> <div class="tabs-body-item" v-if="activeTab === 'admin'">
<p> <p>
Эти настройки пока недоступны, но скоро разработчик это поправит. А пока смотри на крокодила Эти настройки пока недоступны, но скоро разработчик это поправит. А пока смотри на крокодила
</p> </p>
@ -609,6 +609,10 @@
return { modulation: 'qpsk', speed: '1/4' } return { modulation: 'qpsk', speed: '1/4' }
} }
Vue.component('qos-component-root', {
template: ""
})
const app = new Vue({ const app = new Vue({
el: '#app', el: '#app',
data: { data: {
@ -731,7 +735,7 @@
qos: { qos: {
en: false, en: false,
rt1: [{cir: 100, description: 'test class'}], rt1: [{cir: 100, description: 'test class'}, {cir: 200, description: 'fuck class'}],
rt2: [], rt2: [],
rt3: [], rt3: [],
cd: [], cd: [],
@ -916,6 +920,56 @@
case 'rt3': this.qos.rt3.splice(index, 1); break case 'rt3': this.qos.rt3.splice(index, 1); break
case 'cd': this.qos.cd.splice(index, 1); break case 'cd': this.qos.cd.splice(index, 1); break
} }
},
qosDelFilter(name, index, filterIndex) {
switch (name) {
case 'rt1': this.qos.rt1[index].filters.splice(filterIndex, 1); break
case 'rt2': this.qos.rt2[index].filters.splice(filterIndex, 1); break
case 'rt3': this.qos.rt3[index].filters.splice(filterIndex, 1); break
case 'cd': this.qos.cd[index].filters.splice(filterIndex, 1); break
}
},
qosGenerateRuleDescription(filter) {
// попытка 1: просто отобразить все фильтры
let result = ""
let isFirst = true;
for (const key in filter) {
if (!filter[key]) {
continue
}
if (isFirst) {
isFirst = false;
} else {
result += '; '
}
result += `${key}: ${filter[key]}`
}
if (result === "") {
return "пустой"
}
const maxResultLen = 60
if (result.length > maxResultLen) {
// попытка 2, отобразить что вообще в этом фильтре использовалось
result = ""
isFirst = true;
for (const key in filter) {
if (!filter[key]) {
continue
}
if (isFirst) {
isFirst = false;
} else {
result += ', '
}
result += `${key}`
}
}
return result
} }
}, },
mounted() { mounted() {

View File

@ -12,6 +12,7 @@ body {
--bg-selected: #F1F1F1; --bg-selected: #F1F1F1;
--bg-element: #a7a7a7; --bg-element: #a7a7a7;
--bg-action: #5181fe; --bg-action: #5181fe;
--bg-danger: #db2828;
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {