From 44aec3a114d4b2c22c701d0bb39699c73d70e7c0 Mon Sep 17 00:00:00 2001 From: Vladislav Ostapov Date: Fri, 10 Jan 2025 14:28:53 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BC=D0=B8=D0=B3=D1=80=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BD=D0=B0=20vue.js=202.7->3.5;=20=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=87=D0=B8=D0=B9=20front-generator=20(=D1=82=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=B4=D0=BB=D1=8F=20=D0=BC=D0=BE?= =?UTF-8?q?=D0=BD=D0=B8=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=D0=B0=20=D0=B8?= =?UTF-8?q?=20QoS)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 + front-generator/render-params.json | 17 +- front-generator/render.py | 15 +- .../template/common/admin-data.js.j2 | 0 .../template/common/admin-methods.js.j2 | 132 + front-generator/template/common/admin.html.j2 | 87 + .../template/common/monitoring-data.js.j2 | 47 + .../template/common/monitoring-methods.js.j2 | 82 + .../template/common/monitoring.html.j2 | 82 + .../template/common/qos-data.js.j2 | 14 + .../template/common/qos-methods.js.j2 | 243 + front-generator/template/common/qos.html.j2 | 117 + .../template/common/setup-data.js.j2 | 0 .../template/common/setup-methods.js.j2 | 177 + front-generator/template/common/setup.html.j2 | 310 + front-generator/template/default-js.js | 256 +- front-generator/template/main.html | 1311 +- front-generator/template/vue-data.js | 181 - src/main.cpp | 4 + static/dev.html | 96 +- static/js/vue.js | 29805 ++++++++++------ static/js/vue.prod.js | 9 + static/main-scpc.html | 1444 +- static/main-tdma.html | 1023 +- 24 files changed, 20106 insertions(+), 15350 deletions(-) create mode 100644 front-generator/template/common/admin-data.js.j2 create mode 100644 front-generator/template/common/admin-methods.js.j2 create mode 100644 front-generator/template/common/admin.html.j2 create mode 100644 front-generator/template/common/monitoring-data.js.j2 create mode 100644 front-generator/template/common/monitoring-methods.js.j2 create mode 100644 front-generator/template/common/monitoring.html.j2 create mode 100644 front-generator/template/common/qos-data.js.j2 create mode 100644 front-generator/template/common/qos-methods.js.j2 create mode 100644 front-generator/template/common/qos.html.j2 create mode 100644 front-generator/template/common/setup-data.js.j2 create mode 100644 front-generator/template/common/setup-methods.js.j2 create mode 100644 front-generator/template/common/setup.html.j2 delete mode 100644 front-generator/template/vue-data.js create mode 100644 static/js/vue.prod.js diff --git a/.gitignore b/.gitignore index cd6780b..323f570 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,7 @@ cert.pem key.pem dh.pem /web-action + +# эти файлы после генерации должны быть перемещены в `/static` +front-generator/main-scpc.html +front-generator/main-tdma.html diff --git a/front-generator/render-params.json b/front-generator/render-params.json index 84c3c95..bec1081 100644 --- a/front-generator/render-params.json +++ b/front-generator/render-params.json @@ -26,7 +26,7 @@ "modem_types": { "tdma": { "modem_name": "RCSM-101 TDMA", - "groupsList": ["rxtx"], + "groupsList": ["rxtx", "buclnb"], "tabs": [ { "name": "monitoring", @@ -34,14 +34,7 @@ }, { "name": "setup", - "desc": "Настройки", - "widgets": [ - {"group": "html", "name": "h3", "payload": "Настройки передатчика"}, - {"group": "rxtx", "name": "rx.en"}, - {"group": "rxtx", "name": "rx.isTestInputData"}, - {"group": "html", "name": "h3", "payload": "Параметры передачи"}, - {"group": "rxtx", "name": "rx.freqKhz"} - ] + "desc": "Настройки" }, { "name": "admin", @@ -51,7 +44,7 @@ }, "scpc": { "modem_name": "RCSM-101", - "groupsList": ["rxtx"], + "groupsList": ["rxtx", "cinc", "buclnb", "qos", "tcpaccel"], "tabs": [ { "name": "monitoring", @@ -64,10 +57,6 @@ { "name": "qos", "desc": "QoS" - }, - { - "name": "admin", - "desc": "Администрирование" } ] } diff --git a/front-generator/render.py b/front-generator/render.py index 5dbef8f..acf4018 100644 --- a/front-generator/render.py +++ b/front-generator/render.py @@ -1,7 +1,7 @@ import json - from jinja2 import Environment, FileSystemLoader import sys +import os def build_modem_env(modem): @@ -13,10 +13,12 @@ def build_modem_env(modem): mc = config['modem_types'][modem] return { + "modem": modem, "modem_name": mc['modem_name'], "header_tabs": mc['tabs'], - "js_tabs_array": str([t['name'] for t in mc['tabs']]), - "params": {"groupsList": mc["groupsList"]} | config["params"] + "tab_names_array": [t['name'] for t in mc['tabs']], + "params": {"groupsList": mc["groupsList"]} | config["params"], + "all_settings_group_names": [] } @@ -32,8 +34,9 @@ def render_modem(modem): if __name__ == '__main__': - if len(sys.argv) != 2: - print(f"Usage: {sys.argv[0]} ") + render_modem('scpc') + render_modem('tdma') - render_modem(sys.argv[1]) + os.system('cp -u main-tdma.html ../static') + os.system('cp -u main-scpc.html ../static') diff --git a/front-generator/template/common/admin-data.js.j2 b/front-generator/template/common/admin-data.js.j2 new file mode 100644 index 0000000..e69de29 diff --git a/front-generator/template/common/admin-methods.js.j2 b/front-generator/template/common/admin-methods.js.j2 new file mode 100644 index 0000000..b38b336 --- /dev/null +++ b/front-generator/template/common/admin-methods.js.j2 @@ -0,0 +1,132 @@ + settingsSubmitNetwork() { + if (this.submitStatus.network) { return } + let query = { + "network.managementIp": this.param.network.managementIp, + "network.managementGateway": this.param.network.managementGateway, + "network.mode": this.param.network.mode, + "network.dataIp": this.param.network.dataIp, + "network.dataMtu": this.param.network.dataMtu + } + if (confirm('Вы уверены, что хотите сохранить настройки сети? После этого модем может стать недоступным.')) { + this.submitStatus.network = true + fetch('/api/set/network', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(query) + }).then(async (resp) => { + this.submitStatus.network = false + this.updateNetworkSettings(await resp.json()) + }).catch((reason) => { + this.submitStatus.network = false + alert(`Ошибка при применении настроек: ${reason}`) + }) + } + }, + + settingsSubmitDebugSend() { + if (this.submitStatus.debugSend) { return } + let query = { + "debugSend.en": this.param.debugSend.en, + "debugSend.receiverIp": this.param.debugSend.receiverIp, + "debugSend.portCinC": this.param.debugSend.portCinC, + "debugSend.portData": this.param.debugSend.portData, + "debugSend.timeout": this.param.debugSend.timeout + } + this.submitStatus.debugSend = true + fetch('/api/set/debugSend', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(query) + }).then(async (resp) => { + this.submitStatus.debugSend = false + this.updateNetworkSettings(await resp.json()) + }).catch((reason) => { + this.submitStatus.debugSend = false + alert(`Ошибка при применении настроек: ${reason}`) + }) + }, + + async settingsUploadUpdate() { + if (!this.uploadFw.filename) { + alert('Выберите файл для загрузки'); + return; + } + + async function readFileAsArrayBuffer(fileName) { + return new Promise((resolve, reject) => { + if (!fileName) { reject(`Файл не выбран`); return } + const reader = new FileReader(); + reader.onload = (e) => { resolve(reader.result) } + reader.onerror = (e) => { reject(e) } + reader.readAsArrayBuffer(fileName) + }) + } + + try { + this.submitStatus.firmwareUpload = true + this.uploadFw.progress = 0 + const blob = await readFileAsArrayBuffer(this.uploadFw.filename) + + const xhr = new XMLHttpRequest(); + await new Promise((resolve) => { + xhr.upload.addEventListener("progress", (event) => { + if (event.lengthComputable) { + this.uploadFw.progress = Math.round((event.loaded / event.total) * 1000) / 10; + } + }); + xhr.addEventListener("loadend", () => { + this.uploadFw.progress = 100 + const rep = JSON.parse(xhr.responseText); + this.uploadFw.sha256 = rep['sha256'] + resolve(xhr.readyState === 4 && xhr.status === 200); + }); + xhr.open("PUT", "/api/firmwareUpdate", true); + xhr.setRequestHeader("Content-Type", "application/octet-stream"); + xhr.send(blob); + }); + } catch (e) { + alert(`Ошибка загрузки файла: ${e}`); + } + this.submitStatus.firmwareUpload = false + }, + + async settingsPerformFirmwareUpgrade() { + if (this.submitStatus.firmwareUpgrade) { return } + this.submitStatus.firmwareUpgrade = true + try { + await fetch('/api/doFirmwareUpgrade', { method: 'POST' }) + } catch (e) { + console.log("failed to perform upgrade firmware: ", e) + } + this.submitStatus.firmwareUpgrade = false + }, + + updateNetworkSettings(vals) { + this.submitStatus.network = false + this.param.network.managementIp = vals["settings"]["network.managementIp"] + this.param.network.managementGateway = vals["settings"]["network.managementGateway"] + this.param.network.mode = vals["settings"]["network.mode"] + this.param.network.dataIp = vals["settings"]["network.dataIp"] + this.param.network.dataMtu = vals["settings"]["network.dataMtu"] + }, + + updateDebugSendSettings(vals) { + this.submitStatus.debugSend = false + this.param.debugSend.en = vals["settings"]["debugSend.en"] + this.param.debugSend.receiverIp = vals["settings"]["debugSend.receiverIp"] + this.param.debugSend.portCinC = vals["settings"]["debugSend.portCinC"] + this.param.debugSend.portData = vals["settings"]["debugSend.portData"] + this.param.debugSend.timeout = vals["settings"]["debugSend.timeout"] + }, + + doModemReboot() { + if (this.submitStatus.modemReboot !== null) { + return + } + this.submitStatus.modemReboot = 30 + fetch('/api/reboot', { method: 'POST' }).then((r) => {}) + }, diff --git a/front-generator/template/common/admin.html.j2 b/front-generator/template/common/admin.html.j2 new file mode 100644 index 0000000..ad3caa9 --- /dev/null +++ b/front-generator/template/common/admin.html.j2 @@ -0,0 +1,87 @@ + {% raw %} +
+

Настройки сети

+
+

Интерфейс управления

+ + + +

Интерфейс данных

+ + + +
+
+

Отладка

+ + + + + + +
+
+

Управление ПО

+ + + + + + + + +
Версия ПО{{ about.firmwareVersion }}
ID модема{{ about.modemUid }}
Серийный номер{{ about.modemSn }}
MAC интерфейса управления{{ about.macManagement }}
MAC интерфейса управления{{ about.macData }}
+
+ +
+
+ +
+ +

Обновление ПО

+ + + +
+
+ {% endraw %} \ No newline at end of file diff --git a/front-generator/template/common/monitoring-data.js.j2 b/front-generator/template/common/monitoring-data.js.j2 new file mode 100644 index 0000000..cc9fdce --- /dev/null +++ b/front-generator/template/common/monitoring-data.js.j2 @@ -0,0 +1,47 @@ + statRx: { + // индикаторы + state: '?', // общее состояние + sym_sync_lock: '?', // захват символьной + freq_search_lock: '?', // Захват поиска по частоте + afc_lock: '?', // захват ФАПЧ + pkt_sync: '?', // захват пакетной синхронизации + + // куча других параметров, идет в том же порядке, что и в таблице + snr: '?', rssi: '?', + modcod: '?', frameSizeNormal: '?', + isPilots: '?', + symError: '?', + freqErr: '?', freqErrAcc: '?', + inputSignalLevel: '?', + pllError: '?', + speedOnRxKbit: '?', + speedOnIifKbit: '?', + + // статистика пакетов + packetsOk: '?', packetsBad: '?', packetsDummy: '?', + }, + statTx: { + // состояние + state: '?', + + // прочие поля + {% if modem == 'scpc' %} + snr: '?', modcod: '?', frameSizeNormal: '?', isPilots: '?', speedOnTxKbit: '?', speedOnIifKbit: '?', + {% else %} + modcod: '?', speedOnTxKbit: '?', speedOnIifKbit: '?', centerFreq: '?', symSpeed: '?', + {% endif %} + }, + {% if modem == 'scpc' %} + statCinc: { + occ: '?', + correlator: null, + correlatorFails: '?', + freqErr: '?', freqErrAcc: '?', + channelDelay: '?' + }, + {% endif %} + statDevice: { // температурные датчики + adrv: 0, zynq: 0, fpga: 0 + }, + statOs: {uptime: '?'}, + diff --git a/front-generator/template/common/monitoring-methods.js.j2 b/front-generator/template/common/monitoring-methods.js.j2 new file mode 100644 index 0000000..45b1128 --- /dev/null +++ b/front-generator/template/common/monitoring-methods.js.j2 @@ -0,0 +1,82 @@ + updateStatistics(vals) { + this.lastUpdateTime = new Date(); + this.initState = vals["mainState"]["initState"] + {% if modem == 'scpc' %} + this.isCinC = vals["mainState"]["isCinC"] + {% endif %} + + this.statRx.state = vals["mainState"]["rx.state"] + this.statRx.sym_sync_lock = vals["mainState"]["rx.sym_sync_lock"] + this.statRx.freq_search_lock = vals["mainState"]["rx.freq_search_lock"] + this.statRx.afc_lock = vals["mainState"]["rx.afc_lock"] + this.statRx.pkt_sync = vals["mainState"]["rx.pkt_sync"] + this.statRx.snr = vals["mainState"]["rx.snr"] + this.statRx.rssi = vals["mainState"]["rx.rssi"] + this.statRx.modcod = modcodToStr(vals["mainState"]["rx.modcod"]) + this.statRx.frameSizeNormal = vals["mainState"]["rx.frameSizeNormal"] + this.statRx.isPilots = vals["mainState"]["rx.isPilots"] + this.statRx.symError = vals["mainState"]["rx.symError"] + this.statRx.freqErr = vals["mainState"]["rx.freqErr"] + this.statRx.freqErrAcc = vals["mainState"]["rx.freqErrAcc"] + this.statRx.inputSignalLevel = vals["mainState"]["rx.inputSignalLevel"] + this.statRx.pllError = vals["mainState"]["rx.pllError"] + this.statRx.speedOnRxKbit = vals["mainState"]["rx.speedOnRxKbit"] + this.statRx.speedOnIifKbit = vals["mainState"]["rx.speedOnIifKbit"] + this.statRx.packetsOk = vals["mainState"]["rx.packetsOk"] + this.statRx.packetsBad = vals["mainState"]["rx.packetsBad"] + this.statRx.packetsDummy = vals["mainState"]["rx.packetsDummy"] + + {% if modem == 'scpc' %} + this.statTx.state = vals["mainState"]["tx.state"] + this.statTx.snr = vals["mainState"]["tx.snr"] + this.statTx.modcod = modcodToStr(vals["mainState"]["tx.modcod"]) + this.statTx.frameSizeNormal = vals["mainState"]["tx.frameSizeNormal"] + this.statTx.isPilots = vals["mainState"]["tx.isPilots"] + this.statTx.speedOnTxKbit = vals["mainState"]["tx.speedOnTxKbit"] + this.statTx.speedOnIifKbit = vals["mainState"]["tx.speedOnIifKbit"] + + this.statCinc.occ = vals["mainState"]["cinc.occ"] + this.statCinc.correlator = vals["mainState"]["cinc.correlator"] + this.statCinc.correlatorFails = vals["mainState"]["cinc.correlatorFails"] + this.statCinc.freqErr = vals["mainState"]["cinc.freqErr"] + this.statCinc.freqErrAcc = vals["mainState"]["cinc.freqErrAcc"] + this.statCinc.channelDelay = vals["mainState"]["cinc.channelDelay"] + {% else %} + this.statTx.state = vals["mainState"]["tx.state"] + this.statTx.modcod = modcodToStr(vals["mainState"]["tx.modcod"]) + this.statTx.speedOnTxKbit = vals["mainState"]["tx.speedOnTxKbit"] + this.statTx.speedOnIifKbit = vals["mainState"]["tx.speedOnIifKbit"] + this.statTx.centerFreq = vals["mainState"]["tx.centerFreq"] + this.statTx.symSpeed = vals["mainState"]["tx.symSpeed"] + {% endif %} + + this.statDevice.adrv = vals["mainState"]["device.adrv"] + this.statDevice.zynq = vals["mainState"]["device.zynq"] + this.statDevice.fpga = vals["mainState"]["device.fpga"] + + this.testState = vals["mainState"]["testState"] + + // аптайм приходит в секундах, надо преобразовать его в человеко-читаемый вид + let uptime = vals["sysinfo"]["uptime"] + if (uptime) { + let secs = uptime % 60; uptime = Math.floor(uptime / 60) + let mins = uptime % 60; uptime = Math.floor(uptime / 60) + let hours = uptime % 24 + uptime = Math.floor( uptime / 24) + let res = `${hours}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}` + if (uptime > 0) { res = `${uptime} days, ` + res } + this.statOs.uptime = res + } else { + this.statOs.uptime = '?' + } + }, + + resetPacketsStatistics() { + fetch('/api/resetPacketStatistics', { + method: 'POST' + }).then(() => { + this.statRx.packetsOk = 0 + this.statRx.packetsBad = 0 + this.statRx.packetsDummy = 0 + }) + }, \ No newline at end of file diff --git a/front-generator/template/common/monitoring.html.j2 b/front-generator/template/common/monitoring.html.j2 new file mode 100644 index 0000000..07e2b13 --- /dev/null +++ b/front-generator/template/common/monitoring.html.j2 @@ -0,0 +1,82 @@ + {% raw %} +
+
+

Статистика приема

+ + + + + + + + + + + + + + + + + + +
Прием
Захват символьной
Захват ФАПЧ
Захват поиска по частоте
Захват пакетной синхр.
SNR/RSSI{{ statRx.snr }} / {{ statRx.rssi }}
Modcod{{ statRx.modcod }}
Размер кадра{{ statRx.frameSizeNormal ? 'normal' : 'short' }}
Пилот-символы{{ statRx.isPilots ? 'pilots' : 'no pilots' }}
Символьная ошибка{{ statRx.symError }}
Грубая/точная част. ошибка, Гц{{ statRx.freqErr }} / {{ statRx.freqErrAcc }}
Ур. входного сигнала{{ statRx.inputSignalLevel }}
Ошибка ФАПЧ{{ statRx.pllError }}
Инф. скорость на приеме{{ statRx.speedOnRxKbit }} kbit/s
Инф. скорость на интерфейсе{{ statRx.speedOnIifKbit }} kbit/s
+

Статистика пакетов

+ + + + + + +
Качественных пакетов{{ statRx.packetsOk }}
Поврежденных пакетов{{ statRx.packetsBad }}
DUMMY{{ statRx.packetsDummy }}
+ +
+
+

Статистика передачи

{% endraw %}{% if modem == 'scpc' %}{% raw %} + + + + + + + + + + +
Передача
ОСШ дальнего приема{{ statTx.snr }}
Modcod{{ statTx.modcod }}
Размер кадра{{ statTx.frameSizeNormal ? 'normal' : 'short' }}
Пилот-символы{{ statTx.isPilots ? 'pilots' : 'no pilots' }}
Инф. скорость на передаче{{ statTx.speedOnTxKbit }} kbit/s
Инф. скорость на интерфейсе{{ statTx.speedOnIifKbit }} kbit/s
{% endraw %}{% else %}{% raw %} + + + + + + + + + +
Передача
Modcod{{ statTx.modcod }}
Инф. скорость на передаче{{ statTx.speedOnTxKbit }} kbit/s
Инф. скорость на интерфейсе{{ statTx.speedOnIifKbit }} kbit/s
Центральная частота{{ statTx.centerFreq }} kHz
Символьная скорость{{ statTx.symSpeed }} ksymb
{% endraw %}{% endif %}{% raw %} +
{% endraw %}{% if modem == 'scpc' %}{% raw %} +
+

Статистика режима CinC

+ + + + + + + + +
ОСС{{ statCinc.occ }}
Захват коррелятора
Кол-во срывов коррелятора{{ statCinc.correlatorFails }}
Грубая/точная част. ошибка, Гц{{ statCinc.freqErr }} / {{ statCinc.freqErrAcc }}
Задержка в канале, мс{{ statCinc.channelDelay }}
+
{% endraw %}{% endif %}{% raw %} +
+

Состояние устройства

+ + + + + + + +
Температура ADRV{{ statDevice.adrv }} °C
Температура ZYNQ{{ statDevice.zynq }} °C
Температура FPGA{{ statDevice.fpga }} °C
Uptime{{ statOs.uptime }}
+
+
+ {% endraw %} \ No newline at end of file diff --git a/front-generator/template/common/qos-data.js.j2 b/front-generator/template/common/qos-data.js.j2 new file mode 100644 index 0000000..e253188 --- /dev/null +++ b/front-generator/template/common/qos-data.js.j2 @@ -0,0 +1,14 @@ + paramsQos: { + en: false, + rt1: [], + rt2: [], + rt3: [], + cd: [], + }, + {% if 'tcpaccel' in params.groupsList %} + paramsTcpAccel: { + en: false, + maxConnections: 128 + }, + {% endif %} + diff --git a/front-generator/template/common/qos-methods.js.j2 b/front-generator/template/common/qos-methods.js.j2 new file mode 100644 index 0000000..a2feefc --- /dev/null +++ b/front-generator/template/common/qos-methods.js.j2 @@ -0,0 +1,243 @@ + settingsSubmitQoS() { + if (this.submitStatus.qos) { return } + this.submitStatus.qos = true + function _translateQosClass(trafficClass, qc) { + let res = { + cir: qc['cir'], + description: qc['description'], + filters: [] + } + if (trafficClass === 'cd') { + res.pir = qc.pir + } + if (!qc.isEnabled) { + res.disabled = true + } + for (const fi in qc.filters) { + let filter = {} + if (qc['filters'][fi].vlan !== "") { filter['vlan'] = qc['filters'][fi].vlan } + if (qc['filters'][fi].proto.length > 0) { + let tmp = ""; + for (let pid = 0; pid < qc['filters'][fi].proto.length; pid++) { + if (pid !== 0) { tmp += ',' } + tmp += qc['filters'][fi].proto[pid] + } + filter['proto'] = tmp + } + if (qc['filters'][fi].sport !== "") { filter['sport'] = qc['filters'][fi].sport } + if (qc['filters'][fi].dport !== "") { filter['dport'] = qc['filters'][fi].dport } + if (qc['filters'][fi].ip_src !== "") { filter['ip_src'] = qc['filters'][fi].ip_src } + if (qc['filters'][fi].ip_dest !== "") { filter['ip_dest'] = qc['filters'][fi].ip_dest } + if (qc['filters'][fi].dscp !== "") { filter['dscp'] = qc['filters'][fi].dscp } + + if (Object.keys(filter).length === 0) { continue } + if (!qc.filters[fi].isEnabled) { filter['disabled'] = true } + + res.filters.push(filter) + } + if (res.filters.length === 0) { + // автоматическое выключение класса, если правил нет + res.disabled = true + } + + return res + } + let query = { + "en": this.paramsQos.en, + "rt1": [], + "rt2": [], + "rt3": [], + "cd": [] + } + for (let i = 0; i < this.paramsQos.rt1.length; i++) { query.rt1.push(_translateQosClass('rt', this.paramsQos.rt1[i])) } + for (let i = 0; i < this.paramsQos.rt2.length; i++) { query.rt2.push(_translateQosClass('rt', this.paramsQos.rt2[i])) } + for (let i = 0; i < this.paramsQos.rt3.length; i++) { query.rt3.push(_translateQosClass('rt', this.paramsQos.rt3[i])) } + for (let i = 0; i < this.paramsQos.cd.length; i++) { query.cd.push(_translateQosClass('rt', this.paramsQos.cd[i])) } + + console.log(query) + fetch('/api/set/qos', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(query) + }).then(async (resp) => { + this.submitStatus.qos = false + this.updateQosSettings(await resp.json()) + }).catch((reason) => { + this.submitStatus.qos = false + alert(`Ошибка при применении настроек: ${reason}`) + }) + }, + + {% if 'tcpaccel' in params.groupsList %} + settingsSubmitTcpAccel() { + if (this.submitStatus.tcpAccel) { return } + this.submitStatus.tcpAccel = true + fetch('/api/set/tcpAccel', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + "tcpAccel.en": this.param.tcpAccel.en, + "tcpAccel.maxConnections": this.param.tcpAccel.maxConnections + }) + }).then(async (resp) => { + this.submitStatus.tcpAccel = false + this.updateNetworkSettings(await resp.json()) + }).catch((reason) => { + this.submitStatus.tcpAccel = false + alert(`Ошибка при применении настроек: ${reason}`) + }) + }, + {% endif %} + + updateQosSettings(vals) { + this.submitStatus.qos = false + this.paramsQos.en = vals["settings"]["qos.enabled"] + + const qosProfile = vals["settings"]["qos.profile"] + if (qosProfile !== null && qosProfile !== undefined) { + this.paramsQos.rt1 = [] // .splice(0, this.paramsQos.rt1.length) + this.paramsQos.rt2 = [] // .splice(0, this.paramsQos.rt2.length) + this.paramsQos.rt3 = [] // .splice(0, this.paramsQos.rt3.length) + this.paramsQos.cd = [] // .splice(0, this.paramsQos.cd.length) + + for (let trafficClass in qosProfile) { + if (['rt1', 'rt2', 'rt3', 'cd'].indexOf(trafficClass) < 0) { + continue + } + + if (Array.isArray(qosProfile[trafficClass])) { + for (let i = 0; i < qosProfile[trafficClass].length; i++) { + const qc = qosProfile[trafficClass][i] + let result = { + isEnabled: !qc.hasOwnProperty('disabled'), + cir: qc['cir'], + pir: 0, + description: qc['description'], + filters: [] + } + if (trafficClass === 'cd') { + if (qc['pir']) { + result.pir = qc['pir'] + } + } + for (let fi = 0; fi < qc['filters'].length; fi++) { + result.filters.push({ + isEnabled: !qc['filters'][fi].hasOwnProperty('disabled'), + vlan: qc['filters'][fi].hasOwnProperty('vlan') ? qc['filters'][fi]['vlan'] : '', + proto: qc['filters'][fi].hasOwnProperty('proto') ? qc['filters'][fi]['proto'].split(',') : [], + sport: qc['filters'][fi].hasOwnProperty('sport') ? qc['filters'][fi]['sport'] : '', + dport: qc['filters'][fi].hasOwnProperty('dport') ? qc['filters'][fi]['dport'] : '', + ip_src: qc['filters'][fi].hasOwnProperty('ip_src') ? qc['filters'][fi]['ip_src'] : '', + ip_dest: qc['filters'][fi].hasOwnProperty('ip_dest') ? qc['filters'][fi]['ip_dest'] : '', + dscp: qc['filters'][fi].hasOwnProperty('dscp') ? qc['filters'][fi]['dscp'] : '' + }) + } + switch (trafficClass) { + case 'rt1': this.paramsQos.rt1.push(result); break + case 'rt2': this.paramsQos.rt2.push(result); break + case 'rt3': this.paramsQos.rt3.push(result); break + case 'cd': this.paramsQos.cd.push(result); break + } + } + } + } + } + }, + + qosAddClass(name) { + let res = { + isEnabled: true, + cir: 0, + pir: 0, + description: "", + filters: [] + } + switch (name) { + case 'rt1': this.paramsQos.rt1.push(res); break + case 'rt2': this.paramsQos.rt2.push(res); break + case 'rt3': this.paramsQos.rt3.push(res); break + case 'cd': this.paramsQos.cd.push(res); break + } + }, + + qosClassAddRule(name, index) { + let rule = { + isEnabled: true, + vlan: "", + proto: [], + sport: "", + dport: "", + ip_src: "", + ip_dest: "", + dscp: "" + } + switch (name) { + case 'rt1': this.paramsQos.rt1[index].filters.push(rule); break + case 'rt2': this.paramsQos.rt2[index].filters.push(rule); break + case 'rt3': this.paramsQos.rt3[index].filters.push(rule); break + case 'cd': this.paramsQos.cd[index].filters.push(rule); break + } + }, + + qosDelClass(name, index) { + switch (name) { + case 'rt1': this.paramsQos.rt1.splice(index, 1); break + case 'rt2': this.paramsQos.rt2.splice(index, 1); break + case 'rt3': this.paramsQos.rt3.splice(index, 1); break + case 'cd': this.paramsQos.cd.splice(index, 1); break + } + }, + + qosDelFilter(name, index, filterIndex) { + switch (name) { + case 'rt1': this.paramsQos.rt1[index].filters.splice(filterIndex, 1); break + case 'rt2': this.paramsQos.rt2[index].filters.splice(filterIndex, 1); break + case 'rt3': this.paramsQos.rt3[index].filters.splice(filterIndex, 1); break + case 'cd': this.paramsQos.cd[index].filters.splice(filterIndex, 1); break + } + }, + + qosGenerateRuleDescription(filter) { + // попытка 1: просто отобразить все фильтры + let result = "" + let isFirst = true; + for (const key in filter) { + if (key === "isEnabled" || !filter[key] || (key === "proto" && filter['proto'].length === 0)) { + 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 (key === "isEnabled" || !filter[key] || (key === "proto" && filter['proto'].length === 0)) { + continue + } + if (isFirst) { + isFirst = false; + } else { + result += ', ' + } + result += `${key}` + } + } + + return result + }, \ No newline at end of file diff --git a/front-generator/template/common/qos.html.j2 b/front-generator/template/common/qos.html.j2 new file mode 100644 index 0000000..c23bcb1 --- /dev/null +++ b/front-generator/template/common/qos.html.j2 @@ -0,0 +1,117 @@ +{% raw %} +
+

Настройки QoS

+
+ +
+
+

Классы {{ classesGroup.toUpperCase() }}

+
+ + #{{ index }} CIR={{ qosClass.cir }}кбит, PIR={{ qosClass.pir }}кбит {{ qosClass.description }} + #{{ index }} CBR={{ qosClass.cir }}кбит {{ qosClass.description }} + + + + + + + + +

Фильтры ({{ qosClass.filters.length }})

+
+ +
+
+ + #{{ filterIndex }} {{ qosGenerateRuleDescription(filter) }} + + + + + + +
+ Протокол L3 + + + + + + + + + + +
+ + + + + +
+ +
+ +
+
+
+ + + {% endraw %}{% if 'tcpaccel' in params.groupsList %}{% raw %} +

Настройки TCP-акселерации

+
+ + +
+ +
+ {% endraw %}{% endif %} \ No newline at end of file diff --git a/front-generator/template/common/setup-data.js.j2 b/front-generator/template/common/setup-data.js.j2 new file mode 100644 index 0000000..e69de29 diff --git a/front-generator/template/common/setup-methods.js.j2 b/front-generator/template/common/setup-methods.js.j2 new file mode 100644 index 0000000..0f76d56 --- /dev/null +++ b/front-generator/template/common/setup-methods.js.j2 @@ -0,0 +1,177 @@ + settingsSubmitRxTx() { + if (this.submitStatus.rxTx) { return } + // потом добавить: "dvbs2.isPilots": this.param.dvbs2.isPilots + let query = { + "general.isCinC": this.param.general.isCinC, + "general.txEn": this.param.general.txEn, + "general.modulatorMode": this.param.general.modulatorMode, + "general.autoStartTx": this.param.general.autoStartTx, + "general.isTestInputData": this.param.general.isTestInputData, + "tx.attenuation": this.param.tx.attenuation, + "tx.rolloff": this.param.tx.rolloff, + "tx.cymRate": this.param.tx.cymRate, + "tx.centerFreq": this.param.tx.centerFreq, + "dvbs2.isAcm": this.param.dvbs2.mode === 'acm', + "dvbs2.frameSizeNormal": this.param.dvbs2.frameSizeNormal, + "dvbs2.ccm_modcod": toModcod(this.param.dvbs2.ccm_modulation, this.param.dvbs2.ccm_speed), + "dvbs2.acm_minModcod": toModcod(this.param.dvbs2.acm_minModulation, this.param.dvbs2.acm_minSpeed), + "dvbs2.acm_maxModcod": toModcod(this.param.dvbs2.acm_maxModulation, this.param.dvbs2.acm_maxSpeed), + "dvbs2.snrReserve": this.param.dvbs2.snrReserve, + "dvbs2.servicePacketPeriod": this.param.dvbs2.servicePacketPeriod, + "acm.en": this.param.acm.en, + "acm.maxAttenuation": this.param.acm.maxAttenuation, + "acm.minAttenuation": this.param.acm.minAttenuation, + "acm.requiredSnr": this.param.acm.requiredSnr, + "rx.gainMode": this.param.rx.gainMode, + "rx.manualGain": this.param.rx.manualGain, + "rx.spectrumInversion": this.param.rx.spectrumInversion, + "rx.rolloff": this.param.rx.rolloff, + "rx.cymRate": this.param.rx.cymRate, + "rx.centerFreq": this.param.rx.centerFreq + } + + this.submitStatus.rxTx = true + fetch('/api/set/rxtx', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(query) + }).then(async (resp) => { + this.submitStatus.rxTx = false + this.updateRxTxSettings(await resp.json()) + }).catch((reason) => { + this.submitStatus.rxTx = false + alert(`Ошибка при применении настроек: ${reason}`) + }) + }, + + settingsSubmitCinC() { + if (this.submitStatus.cinc) { return } + + let query = { + "cinc.mode": this.param.cinc.mode, + "cinc.searchBandwidth": this.param.cinc.searchBandwidth, + "cinc.position.station.latitude": this.param.cinc.position.station.latitude, + "cinc.position.station.longitude": this.param.cinc.position.station.longitude, + "cinc.position.satelliteLongitude": this.param.cinc.position.satelliteLongitude, + "cinc.delayMin": this.param.cinc.delayMin, + "cinc.delayMax": this.param.cinc.delayMax + } + this.submitStatus.cinc = true + fetch('/api/set/cinc', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(query) + }).then(async (resp) => { + this.submitStatus.cinc = false + this.updateCincSettings(await resp.json()) + }).catch((reason) => { + this.submitStatus.cinc = false + alert(`Ошибка при применении настроек: ${reason}`) + }) + }, + + settingsSubmitBucLnb() { + if (this.submitStatus.bucLnb) { return } + let query = { + "buc.refClk10M": this.param.buc.refClk10M, + "buc.powering": parseInt(this.param.buc.powering), + "lnb.refClk10M": this.param.lnb.refClk10M, + "lnb.powering": parseInt(this.param.lnb.powering), + "serviceSettings.refClk10M": this.param.serviceSettings.refClk10M, + "serviceSettings.autoStart": this.param.serviceSettings.autoStart + } + if (confirm('Вы уверены, что хотите сохранить настройки BUC и LNB?')) { + this.submitStatus.bucLnb = true + fetch('/api/set/bucLnb', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(query) + }).then(async (resp) => { + this.submitStatus.bucLnb = false + this.updateBucLnbSettings(await resp.json()) + }).catch((reason) => { + this.submitStatus.bucLnb = false + alert(`Ошибка при применении настроек: ${reason}`) + }) + } + }, + + updateRxTxSettings(vals) { + this.submitStatus.rxTx = false + this.param.general.isCinC = vals["settings"]["general.isCinC"] + this.param.general.txEn = vals["settings"]["general.txEn"] + this.param.general.modulatorMode = vals["settings"]["general.modulatorMode"] + this.param.general.autoStartTx = vals["settings"]["general.autoStartTx"] + this.param.general.isTestInputData = vals["settings"]["general.isTestInputData"] + + this.param.tx.attenuation = vals["settings"]["tx.attenuation"] + this.param.tx.rolloff = vals["settings"]["tx.rolloff"] + this.param.tx.cymRate = vals["settings"]["tx.cymRate"] + this.param.tx.centerFreq = vals["settings"]["tx.centerFreq"] + + this.param.dvbs2.mode = (vals["settings"]["dvbs2.isAcm"] ? 'acm' : 'ccm') + this.param.dvbs2.frameSizeNormal = vals["settings"]["dvbs2.frameSizeNormal"] + // this.param.dvbs2.isPilots = vals["settings"]["dvbs2.isPilots"] + + let m = extractModulationAndSpeedFromModcod(vals["settings"]["dvbs2.ccm_modcod"]) + this.param.dvbs2.ccm_modulation = m.modulation + this.param.dvbs2.ccm_speed = m.speed + m = extractModulationAndSpeedFromModcod(vals["settings"]["dvbs2.acm_maxModcod"]) + this.param.dvbs2.acm_maxModulation = m.modulation + this.param.dvbs2.acm_maxSpeed = m.speed + m = extractModulationAndSpeedFromModcod(vals["settings"]["dvbs2.acm_minModcod"]) + this.param.dvbs2.acm_minModulation = m.modulation + this.param.dvbs2.acm_minSpeed = m.speed + + this.param.dvbs2.snrReserve = vals["settings"]["dvbs2.snrReserve"] + this.param.dvbs2.servicePacketPeriod = vals["settings"]["dvbs2.servicePacketPeriod"] + + this.param.acm.en = vals["settings"]["acm.en"] + this.param.acm.maxAttenuation = vals["settings"]["acm.maxAttenuation"] + this.param.acm.minAttenuation = vals["settings"]["acm.minAttenuation"] + this.param.acm.requiredSnr = vals["settings"]["acm.requiredSnr"] + + this.param.rx.gainMode = vals["settings"]["rx.gainMode"] + this.param.rx.manualGain = vals["settings"]["rx.manualGain"] + this.param.rx.spectrumInversion = vals["settings"]["rx.spectrumInversion"] + this.param.rx.rolloff = vals["settings"]["rx.rolloff"] + this.param.rx.cymRate = vals["settings"]["rx.cymRate"] + this.param.rx.centerFreq = vals["settings"]["rx.centerFreq"] + }, + + updateCincSettings(vals) { + this.submitStatus.cinc = false + this.param.cinc.mode = vals["settings"]["cinc.mode"] + this.param.cinc.searchBandwidth = vals["settings"]["cinc.searchBandwidth"] + this.param.cinc.position.station.latitude = vals["settings"]["cinc.position.station.latitude"] + this.param.cinc.position.station.longitude = vals["settings"]["cinc.position.station.longitude"] + this.param.cinc.position.satelliteLongitude = vals["settings"]["cinc.position.satelliteLongitude"] + this.param.cinc.delayMin = vals["settings"]["cinc.delayMin"] + this.param.cinc.delayMax = vals["settings"]["cinc.delayMax"] + }, + + updateBucLnbSettings(vals) { + this.submitStatus.bucLnb = false + this.param.buc.refClk10M = vals["settings"]["buc.refClk10M"] + this.param.buc.powering = vals["settings"]["buc.powering"] + this.param.lnb.refClk10M = vals["settings"]["lnb.refClk10M"] + this.param.lnb.powering = vals["settings"]["lnb.powering"] + this.param.serviceSettings.refClk10M = vals["settings"]["serviceSettings.refClk10M"] + this.param.serviceSettings.autoStart = vals["settings"]["serviceSettings.autoStart"] + }, + + updateSettings(vals) { + this.settingFetchComplete = true + this.updateRxTxSettings(vals) + this.updateCincSettings(vals) + this.updateBucLnbSettings(vals) + this.updateQosSettings(vals) + this.updateNetworkSettings(vals) + this.updateDebugSendSettings(vals) + }, \ No newline at end of file diff --git a/front-generator/template/common/setup.html.j2 b/front-generator/template/common/setup.html.j2 new file mode 100644 index 0000000..afc42fe --- /dev/null +++ b/front-generator/template/common/setup.html.j2 @@ -0,0 +1,310 @@ +
+

Настройки приема/передачи

+ +
+ +
+
+
+

Настройки передатчика

+ + + + +

Параметры передачи

+ + + + +
+ +
+

Режим работы DVB-S2

+ + + + + + + + + + + + + + + + + + + + + + +

Авто-регулировка мощности

+ + + + +
+
+

Настройка приемника

+ + + + + + +
+
+ + +

Настройки режима CinC

+
+ + +

Настройки позиционирования

+ + + + +

Задержка до спутника

+ + +
+ + +

Настройки питания и опорного генератора

+
+
+

Настройки BUC

+ + +
+
+

Настройки LNB

+ + +
+
+

Сервисные настройки

+ + +
+
+ +
\ No newline at end of file diff --git a/front-generator/template/default-js.js b/front-generator/template/default-js.js index 049de9c..cbb18f2 100644 --- a/front-generator/template/default-js.js +++ b/front-generator/template/default-js.js @@ -1,139 +1,141 @@ -{% raw %}// для обновления высоты хидера -function updateHeaderHeight() { const header = document.querySelector('header'); document.body.style.setProperty('--header-height', `${header.offsetHeight}px`); } -window.addEventListener('load', updateHeaderHeight); window.addEventListener('resize', updateHeaderHeight); + {% raw %}// default-js.js + // для обновления высоты хидера + 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 + function getCurrentTab() { + const sl = window.location.hash.slice(1) + if (availableTabs.indexOf(sl) >= 0) { + return sl + } + return availableTabs[0] } - return defaultTab -} -function modcodToStr(modcod) { - // модкоды из раздела 5.5.2.2 https://www.etsi.org/deliver/etsi_en/302300_302399/302307/01.01.02_60/en_302307v010102p.pdf + function modcodToStr(modcod) { + // модкоды из раздела 5.5.2.2 https://www.etsi.org/deliver/etsi_en/302300_302399/302307/01.01.02_60/en_302307v010102p.pdf - // NOTE модкоды со скоростью хода 3/5 не работают - const modcods = [ - "DUMMY", - "QPSK 1/4", - "QPSK 1/3", - "QPSK 2/5", - "QPSK 1/2", - "QPSK 3/5", // отключено - "QPSK 2/3", - "QPSK 3/4", - "QPSK 4/5", - "QPSK 5/6", - "QPSK 8/9", - "QPSK 9/10", + // NOTE модкоды со скоростью хода 3/5 не работают + const modcods = [ + "DUMMY", + "QPSK 1/4", + "QPSK 1/3", + "QPSK 2/5", + "QPSK 1/2", + "QPSK 3/5", // отключено + "QPSK 2/3", + "QPSK 3/4", + "QPSK 4/5", + "QPSK 5/6", + "QPSK 8/9", + "QPSK 9/10", - "8PSK 3/5", // отключено - "8PSK 2/3", - "8PSK 3/4", - "8PSK 5/6", - "8PSK 8/9", - "8PSK 9/10", + "8PSK 3/5", // отключено + "8PSK 2/3", + "8PSK 3/4", + "8PSK 5/6", + "8PSK 8/9", + "8PSK 9/10", - "16APSK 2/3", - "16APSK 3/4", - "16APSK 4/5", - "16APSK 5/6", - "16APSK 8/9", - "16APSK 9/10", + "16APSK 2/3", + "16APSK 3/4", + "16APSK 4/5", + "16APSK 5/6", + "16APSK 8/9", + "16APSK 9/10", - "32APSK 3/4", - "32APSK 4/5", - "32APSK 5/6", - "32APSK 8/9", - "32APSK 9/10", - ] - if (typeof modcod != "number" || modcod < 0 || modcod >= modcod.length) { - return "?"; + "32APSK 3/4", + "32APSK 4/5", + "32APSK 5/6", + "32APSK 8/9", + "32APSK 9/10", + ] + if (typeof modcod != "number" || modcod < 0 || modcod >= modcod.length) { + return "?"; + } + return modcods[modcod] } - return modcods[modcod] -} -function toModcod(modulation, speed) { - switch (modulation.toLowerCase()) { - case 'qpsk': - switch (speed) { - case '1/4': return 1 - case '1/3': return 2 - case '2/5': return 3 - case '1/2': return 4 - case '3/5': return 5 // отключено - case '2/3': return 6 - case '3/4': return 7 - case '4/5': return 8 - case '5/6': return 9 - case '8/9': return 10 - case '9/10': return 11 - default: return 1 // минимальная скорость - } - case '8psk': - switch (speed) { - case '3/5': return 12 // отключено - case '2/3': return 13 - case '3/4': return 14 - case '5/6': return 15 - case '8/9': return 16 - case '9/10': return 17 - default: return 13 // минимальная скорость - } - case '16apsk': - switch (speed) { - case '2/3': return 18 - case '3/4': return 19 - case '4/5': return 20 - case '5/6': return 21 - case '8/9': return 22 - case '9/10': return 23 - default: return 18 // минимальная скорость - } - case '32apsk': - switch (speed) { - case '3/4': return 24 - case '4/5': return 25 - case '5/6': return 26 - case '8/9': return 27 - case '9/10': return 28 - default: return 24 - } + function toModcod(modulation, speed) { + switch (modulation.toLowerCase()) { + case 'qpsk': + switch (speed) { + case '1/4': return 1 + case '1/3': return 2 + case '2/5': return 3 + case '1/2': return 4 + case '3/5': return 5 // отключено + case '2/3': return 6 + case '3/4': return 7 + case '4/5': return 8 + case '5/6': return 9 + case '8/9': return 10 + case '9/10': return 11 + default: return 1 // минимальная скорость + } + case '8psk': + switch (speed) { + case '3/5': return 12 // отключено + case '2/3': return 13 + case '3/4': return 14 + case '5/6': return 15 + case '8/9': return 16 + case '9/10': return 17 + default: return 13 // минимальная скорость + } + case '16apsk': + switch (speed) { + case '2/3': return 18 + case '3/4': return 19 + case '4/5': return 20 + case '5/6': return 21 + case '8/9': return 22 + case '9/10': return 23 + default: return 18 // минимальная скорость + } + case '32apsk': + switch (speed) { + case '3/4': return 24 + case '4/5': return 25 + case '5/6': return 26 + case '8/9': return 27 + case '9/10': return 28 + default: return 24 + } + } } -} -function extractModulationAndSpeedFromModcod(modcod) { - switch (modcod) { - case 1: return { modulation: 'qpsk', speed: '1/4' } - case 2: return { modulation: 'qpsk', speed: '1/3' } - case 3: return { modulation: 'qpsk', speed: '2/5' } - case 4: return { modulation: 'qpsk', speed: '1/2' } - case 5: return { modulation: 'qpsk', speed: '3/5' } - case 6: return { modulation: 'qpsk', speed: '2/3' } - case 7: return { modulation: 'qpsk', speed: '3/4' } - case 8: return { modulation: 'qpsk', speed: '4/5' } - case 9: return { modulation: 'qpsk', speed: '5/6' } - case 10: return { modulation: 'qpsk', speed: '8/9' } - case 11: return { modulation: 'qpsk', speed: '9/10' } - case 12: return { modulation: '8psk', speed: '3/5' } - case 13: return { modulation: '8psk', speed: '2/3' } - case 14: return { modulation: '8psk', speed: '3/4' } - case 15: return { modulation: '8psk', speed: '5/6' } - case 16: return { modulation: '8psk', speed: '8/9' } - case 17: return { modulation: '8psk', speed: '9/10' } - case 18: return { modulation: '16apsk', speed: '2/3' } - case 19: return { modulation: '16apsk', speed: '3/4' } - case 20: return { modulation: '16apsk', speed: '4/5' } - case 21: return { modulation: '16apsk', speed: '5/6' } - case 22: return { modulation: '16apsk', speed: '8/9' } - case 23: return { modulation: '16apsk', speed: '9/10' } - case 24: return { modulation: '32apsk', speed: '3/4' } - case 25: return { modulation: '32apsk', speed: '4/5' } - case 26: return { modulation: '32apsk', speed: '5/6' } - case 27: return { modulation: '32apsk', speed: '8/9' } - case 28: return { modulation: '32apsk', speed: '9/10' } + function extractModulationAndSpeedFromModcod(modcod) { + switch (modcod) { + case 1: return { modulation: 'qpsk', speed: '1/4' } + case 2: return { modulation: 'qpsk', speed: '1/3' } + case 3: return { modulation: 'qpsk', speed: '2/5' } + case 4: return { modulation: 'qpsk', speed: '1/2' } + case 5: return { modulation: 'qpsk', speed: '3/5' } + case 6: return { modulation: 'qpsk', speed: '2/3' } + case 7: return { modulation: 'qpsk', speed: '3/4' } + case 8: return { modulation: 'qpsk', speed: '4/5' } + case 9: return { modulation: 'qpsk', speed: '5/6' } + case 10: return { modulation: 'qpsk', speed: '8/9' } + case 11: return { modulation: 'qpsk', speed: '9/10' } + case 12: return { modulation: '8psk', speed: '3/5' } + case 13: return { modulation: '8psk', speed: '2/3' } + case 14: return { modulation: '8psk', speed: '3/4' } + case 15: return { modulation: '8psk', speed: '5/6' } + case 16: return { modulation: '8psk', speed: '8/9' } + case 17: return { modulation: '8psk', speed: '9/10' } + case 18: return { modulation: '16apsk', speed: '2/3' } + case 19: return { modulation: '16apsk', speed: '3/4' } + case 20: return { modulation: '16apsk', speed: '4/5' } + case 21: return { modulation: '16apsk', speed: '5/6' } + case 22: return { modulation: '16apsk', speed: '8/9' } + case 23: return { modulation: '16apsk', speed: '9/10' } + case 24: return { modulation: '32apsk', speed: '3/4' } + case 25: return { modulation: '32apsk', speed: '4/5' } + case 26: return { modulation: '32apsk', speed: '5/6' } + case 27: return { modulation: '32apsk', speed: '8/9' } + case 28: return { modulation: '32apsk', speed: '9/10' } + } + return { modulation: 'qpsk', speed: '1/4' } } - return { modulation: 'qpsk', speed: '1/4' } -} -{% endraw %} \ No newline at end of file + // default-js.js end + {% endraw %} \ No newline at end of file diff --git a/front-generator/template/main.html b/front-generator/template/main.html index d61f90f..27ec312 100644 --- a/front-generator/template/main.html +++ b/front-generator/template/main.html @@ -38,1255 +38,80 @@ \ No newline at end of file diff --git a/front-generator/template/vue-data.js b/front-generator/template/vue-data.js deleted file mode 100644 index 7eb163b..0000000 --- a/front-generator/template/vue-data.js +++ /dev/null @@ -1,181 +0,0 @@ - isCinC: false, - - // false - означает что статистика не отправляется, true - отправляется - submitStatus: { - {% for pg in params.groupsList %} - {{ pg }}: false, - {% endfor %} - firmwareUpload: false, - firmwareUpgrade: false, - // когда модем перезагружается, тут должен быть счетчик. Направление счета - к нулю - modemReboot: null - }, - - stat: { - - } - - stat_rx: { - // индикаторы - state: '?', // общее состояние - sym_sync_lock: '?', // захват символьной - freq_search_lock: '?', // Захват поиска по частоте - afc_lock: '?', // захват ФАПЧ - pkt_sync: '?', // захват пакетной синхронизации - - // куча других параметров, идет в том же порядке, что и в таблице - snr: '?', rssi: '?', - modcod: '?', frameSizeNormal: '?', - isPilots: '?', - symError: '?', - freqErr: '?', freqErrAcc: '?', - inputSignalLevel: '?', - pllError: '?', - speedOnRxKbit: '?', - speedOnIifKbit: '?', - - // статистика пакетов - packetsOk: '?', packetsBad: '?', packetsDummy: '?', - }, - stat_tx: { - // состояние - state: '?', - - // прочие поля - snr: '?', modcod: '?', frameSizeNormal: '?', isPilots: '?', speedOnTxKbit: '?', speedOnIifKbit: '?', - }, - stat_cinc: { - occ: '?', - correlator: null, - correlatorFails: '?', - freqErr: '?', freqErrAcc: '?', - channelDelay: '?' - }, - stat_device: { // температурные датчики - adrv: 0, zynq: 0, fpga: 0 - }, - - param: { - general: { - isCinC: Boolean, - txEn: Boolean, // включен/выключен - modulatorMode: 'normal', // режим работы модулятора - autoStartTx: Boolean, // было "режим работы передатчика" - isTestInputData: Boolean, // входные данные: eth или test - }, - tx: { - attenuation: Number, // ослабление - rolloff: Number, - cymRate: Number, - centerFreq: Number, - }, - dvbs2: { - mode: null, // ccm/acm - frameSizeNormal: null, // 'normal' / 'short' - // isPilots: false, - - // CCM - ccm_modulation: null, - ccm_speed: null, - - // ACM - acm_maxModulation: null, - acm_maxSpeed: null, - acm_minModulation: null, - acm_minSpeed: null, - - snrReserve: null, - servicePacketPeriod: null, - }, - // авто-регулировка мощности - acm: { - en: false, - maxAttenuation: null, - minAttenuation: null, - requiredSnr: null, - }, - rx: { - gainMode: null, // 'auto'/'manual' режим управления усилением - manualGain: 0, // усиление, только для ручного режима - spectrumInversion: false, - rolloff: 0, - cymRate: 100000, - centerFreq: 1200000.0, - }, - - cinc: { - mode: null, // 'positional' | 'delay' - searchBandwidth: 0, // полоса поиска в кГц - position: { - station: { - latitude: 0, - longitude: 0 - }, - satelliteLongitude: 0, - }, - delayMin: 0, - delayMax: 0 - }, - - buc: { - refClk10M: false, // подача опоры 10MHz - powering: 0 // 0, 24, 48 - }, - lnb: { - refClk10M: false, // подача опоры 10MHz - powering: 0 // 0, 13, 18, 24 - }, - serviceSettings: { - refClk10M: false, // подача опоры 10MHz - autoStart: false - }, - - network: { - managementIp: '', // 0.0.0.0/24 - managementGateway: '', - mode: String, // l2 | l3 - dataIp: '', // - dataMtu: 1500 - }, - debugSend: { - en: false, - receiverIp: '0.0.0.0', // 0.0.0.0 - portCinC: 0, - portData: 0, - timeout: 0 - }, - - qos: { - en: false, - rt1: [], - rt2: [], - rt3: [], - cd: [], - }, - - tcpAccel: { - en: false, - maxConnections: 128 - }, - }, - - 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, diff --git a/src/main.cpp b/src/main.cpp index f789d28..ff80f16 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -132,7 +132,11 @@ public: auth.users.emplace_back(std::make_shared("admin", "", http::auth::User::SUPERUSER)); sf->registerFile(staticFilesPath + "/favicon.png", FAVICON_ICO, mime_types::image_png, true); +#ifdef USE_DEBUG sf->registerFile(staticFilesPath + VUE_JS, VUE_JS, mime_types::javascript, true); +#else + sf->registerFile(staticFilesPath + "/js/vue.prod.js", VUE_JS, mime_types::javascript, true); +#endif sf->registerFile(staticFilesPath + STYLE_CSS, STYLE_CSS, mime_types::text_css, true); sf->registerFile(staticFilesPath + FIELDS_CSS, FIELDS_CSS, mime_types::text_css, true); sf->registerFile(staticFilesPath + INDEX_HTML, INDEX_HTML, mime_types::text_html, false); diff --git a/static/dev.html b/static/dev.html index 566549b..7550adf 100644 --- a/static/dev.html +++ b/static/dev.html @@ -2,9 +2,103 @@ - Title + + RSCM-101 + + + + + + + \ No newline at end of file diff --git a/static/js/vue.js b/static/js/vue.js index 49ad25b..04dcc17 100644 --- a/static/js/vue.js +++ b/static/js/vue.js @@ -1,11909 +1,18096 @@ -/*! - * Vue.js v2.7.14 - * (c) 2014-2022 Evan You - * Released under the MIT License. - */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Vue = factory()); -})(this, (function () { 'use strict'; +/** +* vue v3.5.13 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/ +var Vue = (function (exports) { + 'use strict'; - var emptyObject = Object.freeze({}); - var isArray = Array.isArray; - // These helpers produce better VM code in JS engines due to their - // explicitness and function inlining. - function isUndef(v) { - return v === undefined || v === null; + /*! #__NO_SIDE_EFFECTS__ */ + // @__NO_SIDE_EFFECTS__ + function makeMap(str) { + const map = /* @__PURE__ */ Object.create(null); + for (const key of str.split(",")) map[key] = 1; + return (val) => val in map; } - function isDef(v) { - return v !== undefined && v !== null; - } - function isTrue(v) { - return v === true; - } - function isFalse(v) { - return v === false; - } - /** - * Check if value is primitive. - */ - function isPrimitive(value) { - return (typeof value === 'string' || - typeof value === 'number' || - // $flow-disable-line - typeof value === 'symbol' || - typeof value === 'boolean'); - } - function isFunction(value) { - return typeof value === 'function'; - } - /** - * Quick object check - this is primarily used to tell - * objects from primitive values when we know the value - * is a JSON-compliant type. - */ - function isObject(obj) { - return obj !== null && typeof obj === 'object'; - } - /** - * Get the raw type string of a value, e.g., [object Object]. - */ - var _toString = Object.prototype.toString; - function toRawType(value) { - return _toString.call(value).slice(8, -1); - } - /** - * Strict object type check. Only returns true - * for plain JavaScript objects. - */ - function isPlainObject(obj) { - return _toString.call(obj) === '[object Object]'; - } - function isRegExp(v) { - return _toString.call(v) === '[object RegExp]'; - } - /** - * Check if val is a valid array index. - */ - function isValidArrayIndex(val) { - var n = parseFloat(String(val)); - return n >= 0 && Math.floor(n) === n && isFinite(val); - } - function isPromise(val) { - return (isDef(val) && - typeof val.then === 'function' && - typeof val.catch === 'function'); - } - /** - * Convert a value to a string that is actually rendered. - */ - function toString(val) { - return val == null - ? '' - : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString) - ? JSON.stringify(val, null, 2) - : String(val); - } - /** - * Convert an input value to a number for persistence. - * If the conversion fails, return original string. - */ - function toNumber(val) { - var n = parseFloat(val); - return isNaN(n) ? val : n; - } - /** - * Make a map and return a function for checking if a key - * is in that map. - */ - function makeMap(str, expectsLowerCase) { - var map = Object.create(null); - var list = str.split(','); - for (var i = 0; i < list.length; i++) { - map[list[i]] = true; - } - return expectsLowerCase ? function (val) { return map[val.toLowerCase()]; } : function (val) { return map[val]; }; - } - /** - * Check if a tag is a built-in tag. - */ - var isBuiltInTag = makeMap('slot,component', true); - /** - * Check if an attribute is a reserved attribute. - */ - var isReservedAttribute = makeMap('key,ref,slot,slot-scope,is'); - /** - * Remove an item from an array. - */ - function remove$2(arr, item) { - var len = arr.length; - if (len) { - // fast path for the only / last item - if (item === arr[len - 1]) { - arr.length = len - 1; - return; - } - var index = arr.indexOf(item); - if (index > -1) { - return arr.splice(index, 1); - } - } - } - /** - * Check whether an object has the property. - */ - var hasOwnProperty = Object.prototype.hasOwnProperty; - function hasOwn(obj, key) { - return hasOwnProperty.call(obj, key); - } - /** - * Create a cached version of a pure function. - */ - function cached(fn) { - var cache = Object.create(null); - return function cachedFn(str) { - var hit = cache[str]; - return hit || (cache[str] = fn(str)); - }; - } - /** - * Camelize a hyphen-delimited string. - */ - var camelizeRE = /-(\w)/g; - var camelize = cached(function (str) { - return str.replace(camelizeRE, function (_, c) { return (c ? c.toUpperCase() : ''); }); + + const EMPTY_OBJ = Object.freeze({}) ; + const EMPTY_ARR = Object.freeze([]) ; + const NOOP = () => { + }; + const NO = () => false; + const isOn = (key) => key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && // uppercase letter + (key.charCodeAt(2) > 122 || key.charCodeAt(2) < 97); + const isModelListener = (key) => key.startsWith("onUpdate:"); + const extend = Object.assign; + const remove = (arr, el) => { + const i = arr.indexOf(el); + if (i > -1) { + arr.splice(i, 1); + } + }; + const hasOwnProperty$1 = Object.prototype.hasOwnProperty; + const hasOwn = (val, key) => hasOwnProperty$1.call(val, key); + const isArray = Array.isArray; + const isMap = (val) => toTypeString(val) === "[object Map]"; + const isSet = (val) => toTypeString(val) === "[object Set]"; + const isDate = (val) => toTypeString(val) === "[object Date]"; + const isRegExp = (val) => toTypeString(val) === "[object RegExp]"; + const isFunction = (val) => typeof val === "function"; + const isString = (val) => typeof val === "string"; + const isSymbol = (val) => typeof val === "symbol"; + const isObject = (val) => val !== null && typeof val === "object"; + const isPromise = (val) => { + return (isObject(val) || isFunction(val)) && isFunction(val.then) && isFunction(val.catch); + }; + const objectToString = Object.prototype.toString; + const toTypeString = (value) => objectToString.call(value); + const toRawType = (value) => { + return toTypeString(value).slice(8, -1); + }; + const isPlainObject = (val) => toTypeString(val) === "[object Object]"; + const isIntegerKey = (key) => isString(key) && key !== "NaN" && key[0] !== "-" && "" + parseInt(key, 10) === key; + const isReservedProp = /* @__PURE__ */ makeMap( + // the leading comma is intentional so empty string "" is also included + ",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted" + ); + const isBuiltInDirective = /* @__PURE__ */ makeMap( + "bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo" + ); + const cacheStringFunction = (fn) => { + const cache = /* @__PURE__ */ Object.create(null); + return (str) => { + const hit = cache[str]; + return hit || (cache[str] = fn(str)); + }; + }; + const camelizeRE = /-(\w)/g; + const camelize = cacheStringFunction( + (str) => { + return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : ""); + } + ); + const hyphenateRE = /\B([A-Z])/g; + const hyphenate = cacheStringFunction( + (str) => str.replace(hyphenateRE, "-$1").toLowerCase() + ); + const capitalize = cacheStringFunction((str) => { + return str.charAt(0).toUpperCase() + str.slice(1); }); - /** - * Capitalize a string. - */ - var capitalize = cached(function (str) { - return str.charAt(0).toUpperCase() + str.slice(1); - }); - /** - * Hyphenate a camelCase string. - */ - var hyphenateRE = /\B([A-Z])/g; - var hyphenate = cached(function (str) { - return str.replace(hyphenateRE, '-$1').toLowerCase(); - }); - /** - * Simple bind polyfill for environments that do not support it, - * e.g., PhantomJS 1.x. Technically, we don't need this anymore - * since native bind is now performant enough in most browsers. - * But removing it would mean breaking code that was able to run in - * PhantomJS 1.x, so this must be kept for backward compatibility. - */ - /* istanbul ignore next */ - function polyfillBind(fn, ctx) { - function boundFn(a) { - var l = arguments.length; - return l - ? l > 1 - ? fn.apply(ctx, arguments) - : fn.call(ctx, a) - : fn.call(ctx); - } - boundFn._length = fn.length; - return boundFn; + const toHandlerKey = cacheStringFunction( + (str) => { + const s = str ? `on${capitalize(str)}` : ``; + return s; + } + ); + const hasChanged = (value, oldValue) => !Object.is(value, oldValue); + const invokeArrayFns = (fns, ...arg) => { + for (let i = 0; i < fns.length; i++) { + fns[i](...arg); + } + }; + const def = (obj, key, value, writable = false) => { + Object.defineProperty(obj, key, { + configurable: true, + enumerable: false, + writable, + value + }); + }; + const looseToNumber = (val) => { + const n = parseFloat(val); + return isNaN(n) ? val : n; + }; + const toNumber = (val) => { + const n = isString(val) ? Number(val) : NaN; + return isNaN(n) ? val : n; + }; + let _globalThis; + const getGlobalThis = () => { + return _globalThis || (_globalThis = typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {}); + }; + function genCacheKey(source, options) { + return source + JSON.stringify( + options, + (_, val) => typeof val === "function" ? val.toString() : val + ); } - function nativeBind(fn, ctx) { - return fn.bind(ctx); - } - // @ts-expect-error bind cannot be `undefined` - var bind$1 = Function.prototype.bind ? nativeBind : polyfillBind; - /** - * Convert an Array-like object to a real Array. - */ - function toArray(list, start) { - start = start || 0; - var i = list.length - start; - var ret = new Array(i); - while (i--) { - ret[i] = list[i + start]; - } - return ret; - } - /** - * Mix properties into target object. - */ - function extend(to, _from) { - for (var key in _from) { - to[key] = _from[key]; - } - return to; - } - /** - * Merge an Array of Objects into a single Object. - */ - function toObject(arr) { - var res = {}; - for (var i = 0; i < arr.length; i++) { - if (arr[i]) { - extend(res, arr[i]); + + const PatchFlagNames = { + [1]: `TEXT`, + [2]: `CLASS`, + [4]: `STYLE`, + [8]: `PROPS`, + [16]: `FULL_PROPS`, + [32]: `NEED_HYDRATION`, + [64]: `STABLE_FRAGMENT`, + [128]: `KEYED_FRAGMENT`, + [256]: `UNKEYED_FRAGMENT`, + [512]: `NEED_PATCH`, + [1024]: `DYNAMIC_SLOTS`, + [2048]: `DEV_ROOT_FRAGMENT`, + [-1]: `HOISTED`, + [-2]: `BAIL` + }; + + const slotFlagsText = { + [1]: "STABLE", + [2]: "DYNAMIC", + [3]: "FORWARDED" + }; + + const GLOBALS_ALLOWED = "Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,console,Error,Symbol"; + const isGloballyAllowed = /* @__PURE__ */ makeMap(GLOBALS_ALLOWED); + + const range = 2; + function generateCodeFrame(source, start = 0, end = source.length) { + start = Math.max(0, Math.min(start, source.length)); + end = Math.max(0, Math.min(end, source.length)); + if (start > end) return ""; + let lines = source.split(/(\r?\n)/); + const newlineSequences = lines.filter((_, idx) => idx % 2 === 1); + lines = lines.filter((_, idx) => idx % 2 === 0); + let count = 0; + const res = []; + for (let i = 0; i < lines.length; i++) { + count += lines[i].length + (newlineSequences[i] && newlineSequences[i].length || 0); + if (count >= start) { + for (let j = i - range; j <= i + range || end > count; j++) { + if (j < 0 || j >= lines.length) continue; + const line = j + 1; + res.push( + `${line}${" ".repeat(Math.max(3 - String(line).length, 0))}| ${lines[j]}` + ); + const lineLength = lines[j].length; + const newLineSeqLength = newlineSequences[j] && newlineSequences[j].length || 0; + if (j === i) { + const pad = start - (count - (lineLength + newLineSeqLength)); + const length = Math.max( + 1, + end > count ? lineLength - pad : end - start + ); + res.push(` | ` + " ".repeat(pad) + "^".repeat(length)); + } else if (j > i) { + if (end > count) { + const length = Math.max(Math.min(end - count, lineLength), 1); + res.push(` | ` + "^".repeat(length)); + } + count += lineLength + newLineSeqLength; } + } + break; + } + } + return res.join("\n"); + } + + function normalizeStyle(value) { + if (isArray(value)) { + const res = {}; + for (let i = 0; i < value.length; i++) { + const item = value[i]; + const normalized = isString(item) ? parseStringStyle(item) : normalizeStyle(item); + if (normalized) { + for (const key in normalized) { + res[key] = normalized[key]; + } + } } return res; - } - /* eslint-disable no-unused-vars */ - /** - * Perform no operation. - * Stubbing args to make Flow happy without leaving useless transpiled code - * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/). - */ - function noop(a, b, c) { } - /** - * Always return false. - */ - var no = function (a, b, c) { return false; }; - /* eslint-enable no-unused-vars */ - /** - * Return the same value. - */ - var identity = function (_) { return _; }; - /** - * Generate a string containing static keys from compiler modules. - */ - function genStaticKeys$1(modules) { - return modules - .reduce(function (keys, m) { - return keys.concat(m.staticKeys || []); - }, []) - .join(','); - } - /** - * Check if two values are loosely equal - that is, - * if they are plain objects, do they have the same shape? - */ - function looseEqual(a, b) { - if (a === b) - return true; - var isObjectA = isObject(a); - var isObjectB = isObject(b); - if (isObjectA && isObjectB) { - try { - var isArrayA = Array.isArray(a); - var isArrayB = Array.isArray(b); - if (isArrayA && isArrayB) { - return (a.length === b.length && - a.every(function (e, i) { - return looseEqual(e, b[i]); - })); - } - else if (a instanceof Date && b instanceof Date) { - return a.getTime() === b.getTime(); - } - else if (!isArrayA && !isArrayB) { - var keysA = Object.keys(a); - var keysB = Object.keys(b); - return (keysA.length === keysB.length && - keysA.every(function (key) { - return looseEqual(a[key], b[key]); - })); - } - else { - /* istanbul ignore next */ - return false; - } - } - catch (e) { - /* istanbul ignore next */ - return false; - } - } - else if (!isObjectA && !isObjectB) { - return String(a) === String(b); - } - else { - return false; - } - } - /** - * Return the first index at which a loosely equal value can be - * found in the array (if value is a plain object, the array must - * contain an object of the same shape), or -1 if it is not present. - */ - function looseIndexOf(arr, val) { - for (var i = 0; i < arr.length; i++) { - if (looseEqual(arr[i], val)) - return i; - } - return -1; - } - /** - * Ensure a function is called only once. - */ - function once(fn) { - var called = false; - return function () { - if (!called) { - called = true; - fn.apply(this, arguments); - } - }; - } - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#polyfill - function hasChanged(x, y) { - if (x === y) { - return x === 0 && 1 / x !== 1 / y; - } - else { - return x === x || y === y; - } - } - - var SSR_ATTR = 'data-server-rendered'; - var ASSET_TYPES = ['component', 'directive', 'filter']; - var LIFECYCLE_HOOKS = [ - 'beforeCreate', - 'created', - 'beforeMount', - 'mounted', - 'beforeUpdate', - 'updated', - 'beforeDestroy', - 'destroyed', - 'activated', - 'deactivated', - 'errorCaptured', - 'serverPrefetch', - 'renderTracked', - 'renderTriggered' - ]; - - var config = { - /** - * Option merge strategies (used in core/util/options) - */ - // $flow-disable-line - optionMergeStrategies: Object.create(null), - /** - * Whether to suppress warnings. - */ - silent: false, - /** - * Show production mode tip message on boot? - */ - productionTip: true, - /** - * Whether to enable devtools - */ - devtools: true, - /** - * Whether to record perf - */ - performance: false, - /** - * Error handler for watcher errors - */ - errorHandler: null, - /** - * Warn handler for watcher warns - */ - warnHandler: null, - /** - * Ignore certain custom elements - */ - ignoredElements: [], - /** - * Custom user key aliases for v-on - */ - // $flow-disable-line - keyCodes: Object.create(null), - /** - * Check if a tag is reserved so that it cannot be registered as a - * component. This is platform-dependent and may be overwritten. - */ - isReservedTag: no, - /** - * Check if an attribute is reserved so that it cannot be used as a component - * prop. This is platform-dependent and may be overwritten. - */ - isReservedAttr: no, - /** - * Check if a tag is an unknown element. - * Platform-dependent. - */ - isUnknownElement: no, - /** - * Get the namespace of an element - */ - getTagNamespace: noop, - /** - * Parse the real tag name for the specific platform. - */ - parsePlatformTagName: identity, - /** - * Check if an attribute must be bound using property, e.g. value - * Platform-dependent. - */ - mustUseProp: no, - /** - * Perform updates asynchronously. Intended to be used by Vue Test Utils - * This will significantly reduce performance if set to false. - */ - async: true, - /** - * Exposed for legacy reasons - */ - _lifecycleHooks: LIFECYCLE_HOOKS - }; - - /** - * unicode letters used for parsing html tags, component names and property paths. - * using https://www.w3.org/TR/html53/semantics-scripting.html#potentialcustomelementname - * skipping \u10000-\uEFFFF due to it freezing up PhantomJS - */ - var unicodeRegExp = /a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/; - /** - * Check if a string starts with $ or _ - */ - function isReserved(str) { - var c = (str + '').charCodeAt(0); - return c === 0x24 || c === 0x5f; - } - /** - * Define a property. - */ - function def(obj, key, val, enumerable) { - Object.defineProperty(obj, key, { - value: val, - enumerable: !!enumerable, - writable: true, - configurable: true - }); - } - /** - * Parse simple path. - */ - var bailRE = new RegExp("[^".concat(unicodeRegExp.source, ".$_\\d]")); - function parsePath(path) { - if (bailRE.test(path)) { - return; - } - var segments = path.split('.'); - return function (obj) { - for (var i = 0; i < segments.length; i++) { - if (!obj) - return; - obj = obj[segments[i]]; - } - return obj; - }; - } - - // can we use __proto__? - var hasProto = '__proto__' in {}; - // Browser environment sniffing - var inBrowser = typeof window !== 'undefined'; - var UA = inBrowser && window.navigator.userAgent.toLowerCase(); - var isIE = UA && /msie|trident/.test(UA); - var isIE9 = UA && UA.indexOf('msie 9.0') > 0; - var isEdge = UA && UA.indexOf('edge/') > 0; - UA && UA.indexOf('android') > 0; - var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA); - UA && /chrome\/\d+/.test(UA) && !isEdge; - UA && /phantomjs/.test(UA); - var isFF = UA && UA.match(/firefox\/(\d+)/); - // Firefox has a "watch" function on Object.prototype... - // @ts-expect-error firebox support - var nativeWatch = {}.watch; - var supportsPassive = false; - if (inBrowser) { - try { - var opts = {}; - Object.defineProperty(opts, 'passive', { - get: function () { - /* istanbul ignore next */ - supportsPassive = true; - } - }); // https://github.com/facebook/flow/issues/285 - window.addEventListener('test-passive', null, opts); - } - catch (e) { } - } - // this needs to be lazy-evaled because vue may be required before - // vue-server-renderer can set VUE_ENV - var _isServer; - var isServerRendering = function () { - if (_isServer === undefined) { - /* istanbul ignore if */ - if (!inBrowser && typeof global !== 'undefined') { - // detect presence of vue-server-renderer and avoid - // Webpack shimming the process - _isServer = - global['process'] && global['process'].env.VUE_ENV === 'server'; - } - else { - _isServer = false; - } - } - return _isServer; - }; - // detect devtools - var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; - /* istanbul ignore next */ - function isNative(Ctor) { - return typeof Ctor === 'function' && /native code/.test(Ctor.toString()); - } - var hasSymbol = typeof Symbol !== 'undefined' && - isNative(Symbol) && - typeof Reflect !== 'undefined' && - isNative(Reflect.ownKeys); - var _Set; // $flow-disable-line - /* istanbul ignore if */ if (typeof Set !== 'undefined' && isNative(Set)) { - // use native Set when available. - _Set = Set; - } - else { - // a non-standard Set polyfill that only works with primitive keys. - _Set = /** @class */ (function () { - function Set() { - this.set = Object.create(null); - } - Set.prototype.has = function (key) { - return this.set[key] === true; - }; - Set.prototype.add = function (key) { - this.set[key] = true; - }; - Set.prototype.clear = function () { - this.set = Object.create(null); - }; - return Set; - }()); - } - - var currentInstance = null; - /** - * This is exposed for compatibility with v3 (e.g. some functions in VueUse - * relies on it). Do not use this internally, just use `currentInstance`. - * - * @internal this function needs manual type declaration because it relies - * on previously manually authored types from Vue 2 - */ - function getCurrentInstance() { - return currentInstance && { proxy: currentInstance }; - } - /** - * @internal - */ - function setCurrentInstance(vm) { - if (vm === void 0) { vm = null; } - if (!vm) - currentInstance && currentInstance._scope.off(); - currentInstance = vm; - vm && vm._scope.on(); - } - - /** - * @internal - */ - var VNode = /** @class */ (function () { - function VNode(tag, data, children, text, elm, context, componentOptions, asyncFactory) { - this.tag = tag; - this.data = data; - this.children = children; - this.text = text; - this.elm = elm; - this.ns = undefined; - this.context = context; - this.fnContext = undefined; - this.fnOptions = undefined; - this.fnScopeId = undefined; - this.key = data && data.key; - this.componentOptions = componentOptions; - this.componentInstance = undefined; - this.parent = undefined; - this.raw = false; - this.isStatic = false; - this.isRootInsert = true; - this.isComment = false; - this.isCloned = false; - this.isOnce = false; - this.asyncFactory = asyncFactory; - this.asyncMeta = undefined; - this.isAsyncPlaceholder = false; - } - Object.defineProperty(VNode.prototype, "child", { - // DEPRECATED: alias for componentInstance for backwards compat. - /* istanbul ignore next */ - get: function () { - return this.componentInstance; - }, - enumerable: false, - configurable: true - }); - return VNode; - }()); - var createEmptyVNode = function (text) { - if (text === void 0) { text = ''; } - var node = new VNode(); - node.text = text; - node.isComment = true; - return node; - }; - function createTextVNode(val) { - return new VNode(undefined, undefined, undefined, String(val)); - } - // optimized shallow clone - // used for static nodes and slot nodes because they may be reused across - // multiple renders, cloning them avoids errors when DOM manipulations rely - // on their elm reference. - function cloneVNode(vnode) { - var cloned = new VNode(vnode.tag, vnode.data, - // #7975 - // clone children array to avoid mutating original in case of cloning - // a child. - vnode.children && vnode.children.slice(), vnode.text, vnode.elm, vnode.context, vnode.componentOptions, vnode.asyncFactory); - cloned.ns = vnode.ns; - cloned.isStatic = vnode.isStatic; - cloned.key = vnode.key; - cloned.isComment = vnode.isComment; - cloned.fnContext = vnode.fnContext; - cloned.fnOptions = vnode.fnOptions; - cloned.fnScopeId = vnode.fnScopeId; - cloned.asyncMeta = vnode.asyncMeta; - cloned.isCloned = true; - return cloned; - } - - /* not type checking this file because flow doesn't play well with Proxy */ - var initProxy; - { - var allowedGlobals_1 = makeMap('Infinity,undefined,NaN,isFinite,isNaN,' + - 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + - 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,' + - 'require' // for Webpack/Browserify - ); - var warnNonPresent_1 = function (target, key) { - warn$2("Property or method \"".concat(key, "\" is not defined on the instance but ") + - 'referenced during render. Make sure that this property is reactive, ' + - 'either in the data option, or for class-based components, by ' + - 'initializing the property. ' + - 'See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.', target); - }; - var warnReservedPrefix_1 = function (target, key) { - warn$2("Property \"".concat(key, "\" must be accessed with \"$data.").concat(key, "\" because ") + - 'properties starting with "$" or "_" are not proxied in the Vue instance to ' + - 'prevent conflicts with Vue internals. ' + - 'See: https://v2.vuejs.org/v2/api/#data', target); - }; - var hasProxy_1 = typeof Proxy !== 'undefined' && isNative(Proxy); - if (hasProxy_1) { - var isBuiltInModifier_1 = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact'); - config.keyCodes = new Proxy(config.keyCodes, { - set: function (target, key, value) { - if (isBuiltInModifier_1(key)) { - warn$2("Avoid overwriting built-in modifier in config.keyCodes: .".concat(key)); - return false; - } - else { - target[key] = value; - return true; - } - } - }); - } - var hasHandler_1 = { - has: function (target, key) { - var has = key in target; - var isAllowed = allowedGlobals_1(key) || - (typeof key === 'string' && - key.charAt(0) === '_' && - !(key in target.$data)); - if (!has && !isAllowed) { - if (key in target.$data) - warnReservedPrefix_1(target, key); - else - warnNonPresent_1(target, key); - } - return has || !isAllowed; - } - }; - var getHandler_1 = { - get: function (target, key) { - if (typeof key === 'string' && !(key in target)) { - if (key in target.$data) - warnReservedPrefix_1(target, key); - else - warnNonPresent_1(target, key); - } - return target[key]; - } - }; - initProxy = function initProxy(vm) { - if (hasProxy_1) { - // determine which proxy handler to use - var options = vm.$options; - var handlers = options.render && options.render._withStripped ? getHandler_1 : hasHandler_1; - vm._renderProxy = new Proxy(vm, handlers); - } - else { - vm._renderProxy = vm; - } - }; - } - - /****************************************************************************** - Copyright (c) Microsoft Corporation. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. - ***************************************************************************** */ - - var __assign = function() { - __assign = Object.assign || function __assign(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); - }; - - var uid$2 = 0; - var pendingCleanupDeps = []; - var cleanupDeps = function () { - for (var i = 0; i < pendingCleanupDeps.length; i++) { - var dep = pendingCleanupDeps[i]; - dep.subs = dep.subs.filter(function (s) { return s; }); - dep._pending = false; - } - pendingCleanupDeps.length = 0; - }; - /** - * A dep is an observable that can have multiple - * directives subscribing to it. - * @internal - */ - var Dep = /** @class */ (function () { - function Dep() { - // pending subs cleanup - this._pending = false; - this.id = uid$2++; - this.subs = []; - } - Dep.prototype.addSub = function (sub) { - this.subs.push(sub); - }; - Dep.prototype.removeSub = function (sub) { - // #12696 deps with massive amount of subscribers are extremely slow to - // clean up in Chromium - // to workaround this, we unset the sub for now, and clear them on - // next scheduler flush. - this.subs[this.subs.indexOf(sub)] = null; - if (!this._pending) { - this._pending = true; - pendingCleanupDeps.push(this); - } - }; - Dep.prototype.depend = function (info) { - if (Dep.target) { - Dep.target.addDep(this); - if (info && Dep.target.onTrack) { - Dep.target.onTrack(__assign({ effect: Dep.target }, info)); - } - } - }; - Dep.prototype.notify = function (info) { - // stabilize the subscriber list first - var subs = this.subs.filter(function (s) { return s; }); - if (!config.async) { - // subs aren't sorted in scheduler if not running async - // we need to sort them now to make sure they fire in correct - // order - subs.sort(function (a, b) { return a.id - b.id; }); - } - for (var i = 0, l = subs.length; i < l; i++) { - var sub = subs[i]; - if (info) { - sub.onTrigger && - sub.onTrigger(__assign({ effect: subs[i] }, info)); - } - sub.update(); - } - }; - return Dep; - }()); - // The current target watcher being evaluated. - // This is globally unique because only one watcher - // can be evaluated at a time. - Dep.target = null; - var targetStack = []; - function pushTarget(target) { - targetStack.push(target); - Dep.target = target; - } - function popTarget() { - targetStack.pop(); - Dep.target = targetStack[targetStack.length - 1]; - } - - /* - * not type checking this file because flow doesn't play well with - * dynamically accessing methods on Array prototype - */ - var arrayProto = Array.prototype; - var arrayMethods = Object.create(arrayProto); - var methodsToPatch = [ - 'push', - 'pop', - 'shift', - 'unshift', - 'splice', - 'sort', - 'reverse' - ]; - /** - * Intercept mutating methods and emit events - */ - methodsToPatch.forEach(function (method) { - // cache original method - var original = arrayProto[method]; - def(arrayMethods, method, function mutator() { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - var result = original.apply(this, args); - var ob = this.__ob__; - var inserted; - switch (method) { - case 'push': - case 'unshift': - inserted = args; - break; - case 'splice': - inserted = args.slice(2); - break; - } - if (inserted) - ob.observeArray(inserted); - // notify change - { - ob.dep.notify({ - type: "array mutation" /* TriggerOpTypes.ARRAY_MUTATION */, - target: this, - key: method - }); - } - return result; - }); - }); - - var arrayKeys = Object.getOwnPropertyNames(arrayMethods); - var NO_INIITIAL_VALUE = {}; - /** - * In some cases we may want to disable observation inside a component's - * update computation. - */ - var shouldObserve = true; - function toggleObserving(value) { - shouldObserve = value; - } - // ssr mock dep - var mockDep = { - notify: noop, - depend: noop, - addSub: noop, - removeSub: noop - }; - /** - * Observer class that is attached to each observed - * object. Once attached, the observer converts the target - * object's property keys into getter/setters that - * collect dependencies and dispatch updates. - */ - var Observer = /** @class */ (function () { - function Observer(value, shallow, mock) { - if (shallow === void 0) { shallow = false; } - if (mock === void 0) { mock = false; } - this.value = value; - this.shallow = shallow; - this.mock = mock; - // this.value = value - this.dep = mock ? mockDep : new Dep(); - this.vmCount = 0; - def(value, '__ob__', this); - if (isArray(value)) { - if (!mock) { - if (hasProto) { - value.__proto__ = arrayMethods; - /* eslint-enable no-proto */ - } - else { - for (var i = 0, l = arrayKeys.length; i < l; i++) { - var key = arrayKeys[i]; - def(value, key, arrayMethods[key]); - } - } - } - if (!shallow) { - this.observeArray(value); - } - } - else { - /** - * Walk through all properties and convert them into - * getter/setters. This method should only be called when - * value type is Object. - */ - var keys = Object.keys(value); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - defineReactive(value, key, NO_INIITIAL_VALUE, undefined, shallow, mock); - } - } - } - /** - * Observe a list of Array items. - */ - Observer.prototype.observeArray = function (value) { - for (var i = 0, l = value.length; i < l; i++) { - observe(value[i], false, this.mock); - } - }; - return Observer; - }()); - // helpers - /** - * Attempt to create an observer instance for a value, - * returns the new observer if successfully observed, - * or the existing observer if the value already has one. - */ - function observe(value, shallow, ssrMockReactivity) { - if (value && hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { - return value.__ob__; - } - if (shouldObserve && - (ssrMockReactivity || !isServerRendering()) && - (isArray(value) || isPlainObject(value)) && - Object.isExtensible(value) && - !value.__v_skip /* ReactiveFlags.SKIP */ && - !isRef(value) && - !(value instanceof VNode)) { - return new Observer(value, shallow, ssrMockReactivity); - } - } - /** - * Define a reactive property on an Object. - */ - function defineReactive(obj, key, val, customSetter, shallow, mock) { - var dep = new Dep(); - var property = Object.getOwnPropertyDescriptor(obj, key); - if (property && property.configurable === false) { - return; - } - // cater for pre-defined getter/setters - var getter = property && property.get; - var setter = property && property.set; - if ((!getter || setter) && - (val === NO_INIITIAL_VALUE || arguments.length === 2)) { - val = obj[key]; - } - var childOb = !shallow && observe(val, false, mock); - Object.defineProperty(obj, key, { - enumerable: true, - configurable: true, - get: function reactiveGetter() { - var value = getter ? getter.call(obj) : val; - if (Dep.target) { - { - dep.depend({ - target: obj, - type: "get" /* TrackOpTypes.GET */, - key: key - }); - } - if (childOb) { - childOb.dep.depend(); - if (isArray(value)) { - dependArray(value); - } - } - } - return isRef(value) && !shallow ? value.value : value; - }, - set: function reactiveSetter(newVal) { - var value = getter ? getter.call(obj) : val; - if (!hasChanged(value, newVal)) { - return; - } - if (customSetter) { - customSetter(); - } - if (setter) { - setter.call(obj, newVal); - } - else if (getter) { - // #7981: for accessor properties without setter - return; - } - else if (!shallow && isRef(value) && !isRef(newVal)) { - value.value = newVal; - return; - } - else { - val = newVal; - } - childOb = !shallow && observe(newVal, false, mock); - { - dep.notify({ - type: "set" /* TriggerOpTypes.SET */, - target: obj, - key: key, - newValue: newVal, - oldValue: value - }); - } - } - }); - return dep; - } - function set(target, key, val) { - if ((isUndef(target) || isPrimitive(target))) { - warn$2("Cannot set reactive property on undefined, null, or primitive value: ".concat(target)); - } - if (isReadonly(target)) { - warn$2("Set operation on key \"".concat(key, "\" failed: target is readonly.")); - return; - } - var ob = target.__ob__; - if (isArray(target) && isValidArrayIndex(key)) { - target.length = Math.max(target.length, key); - target.splice(key, 1, val); - // when mocking for SSR, array methods are not hijacked - if (ob && !ob.shallow && ob.mock) { - observe(val, false, true); - } - return val; - } - if (key in target && !(key in Object.prototype)) { - target[key] = val; - return val; - } - if (target._isVue || (ob && ob.vmCount)) { - warn$2('Avoid adding reactive properties to a Vue instance or its root $data ' + - 'at runtime - declare it upfront in the data option.'); - return val; - } - if (!ob) { - target[key] = val; - return val; - } - defineReactive(ob.value, key, val, undefined, ob.shallow, ob.mock); - { - ob.dep.notify({ - type: "add" /* TriggerOpTypes.ADD */, - target: target, - key: key, - newValue: val, - oldValue: undefined - }); - } - return val; - } - function del(target, key) { - if ((isUndef(target) || isPrimitive(target))) { - warn$2("Cannot delete reactive property on undefined, null, or primitive value: ".concat(target)); - } - if (isArray(target) && isValidArrayIndex(key)) { - target.splice(key, 1); - return; - } - var ob = target.__ob__; - if (target._isVue || (ob && ob.vmCount)) { - warn$2('Avoid deleting properties on a Vue instance or its root $data ' + - '- just set it to null.'); - return; - } - if (isReadonly(target)) { - warn$2("Delete operation on key \"".concat(key, "\" failed: target is readonly.")); - return; - } - if (!hasOwn(target, key)) { - return; - } - delete target[key]; - if (!ob) { - return; - } - { - ob.dep.notify({ - type: "delete" /* TriggerOpTypes.DELETE */, - target: target, - key: key - }); - } - } - /** - * Collect dependencies on array elements when the array is touched, since - * we cannot intercept array element access like property getters. - */ - function dependArray(value) { - for (var e = void 0, i = 0, l = value.length; i < l; i++) { - e = value[i]; - if (e && e.__ob__) { - e.__ob__.dep.depend(); - } - if (isArray(e)) { - dependArray(e); - } - } - } - - function reactive(target) { - makeReactive(target, false); - return target; - } - /** - * Return a shallowly-reactive copy of the original object, where only the root - * level properties are reactive. It also does not auto-unwrap refs (even at the - * root level). - */ - function shallowReactive(target) { - makeReactive(target, true); - def(target, "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */, true); - return target; - } - function makeReactive(target, shallow) { - // if trying to observe a readonly proxy, return the readonly version. - if (!isReadonly(target)) { - { - if (isArray(target)) { - warn$2("Avoid using Array as root value for ".concat(shallow ? "shallowReactive()" : "reactive()", " as it cannot be tracked in watch() or watchEffect(). Use ").concat(shallow ? "shallowRef()" : "ref()", " instead. This is a Vue-2-only limitation.")); - } - var existingOb = target && target.__ob__; - if (existingOb && existingOb.shallow !== shallow) { - warn$2("Target is already a ".concat(existingOb.shallow ? "" : "non-", "shallow reactive object, and cannot be converted to ").concat(shallow ? "" : "non-", "shallow.")); - } - } - var ob = observe(target, shallow, isServerRendering() /* ssr mock reactivity */); - if (!ob) { - if (target == null || isPrimitive(target)) { - warn$2("value cannot be made reactive: ".concat(String(target))); - } - if (isCollectionType(target)) { - warn$2("Vue 2 does not support reactive collection types such as Map or Set."); - } - } - } - } - function isReactive(value) { - if (isReadonly(value)) { - return isReactive(value["__v_raw" /* ReactiveFlags.RAW */]); - } - return !!(value && value.__ob__); - } - function isShallow(value) { - return !!(value && value.__v_isShallow); - } - function isReadonly(value) { - return !!(value && value.__v_isReadonly); - } - function isProxy(value) { - return isReactive(value) || isReadonly(value); - } - function toRaw(observed) { - var raw = observed && observed["__v_raw" /* ReactiveFlags.RAW */]; - return raw ? toRaw(raw) : observed; - } - function markRaw(value) { - // non-extensible objects won't be observed anyway - if (Object.isExtensible(value)) { - def(value, "__v_skip" /* ReactiveFlags.SKIP */, true); - } + } else if (isString(value) || isObject(value)) { return value; + } } - /** - * @internal - */ - function isCollectionType(value) { - var type = toRawType(value); - return (type === 'Map' || type === 'WeakMap' || type === 'Set' || type === 'WeakSet'); + const listDelimiterRE = /;(?![^(]*\))/g; + const propertyDelimiterRE = /:([^]+)/; + const styleCommentRE = /\/\*[^]*?\*\//g; + function parseStringStyle(cssText) { + const ret = {}; + cssText.replace(styleCommentRE, "").split(listDelimiterRE).forEach((item) => { + if (item) { + const tmp = item.split(propertyDelimiterRE); + tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim()); + } + }); + return ret; + } + function stringifyStyle(styles) { + if (!styles) return ""; + if (isString(styles)) return styles; + let ret = ""; + for (const key in styles) { + const value = styles[key]; + if (isString(value) || typeof value === "number") { + const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key); + ret += `${normalizedKey}:${value};`; + } + } + return ret; + } + function normalizeClass(value) { + let res = ""; + if (isString(value)) { + res = value; + } else if (isArray(value)) { + for (let i = 0; i < value.length; i++) { + const normalized = normalizeClass(value[i]); + if (normalized) { + res += normalized + " "; + } + } + } else if (isObject(value)) { + for (const name in value) { + if (value[name]) { + res += name + " "; + } + } + } + return res.trim(); + } + function normalizeProps(props) { + if (!props) return null; + let { class: klass, style } = props; + if (klass && !isString(klass)) { + props.class = normalizeClass(klass); + } + if (style) { + props.style = normalizeStyle(style); + } + return props; } - /** - * @internal - */ - var RefFlag = "__v_isRef"; - function isRef(r) { - return !!(r && r.__v_isRef === true); - } - function ref$1(value) { - return createRef(value, false); - } - function shallowRef(value) { - return createRef(value, true); - } - function createRef(rawValue, shallow) { - if (isRef(rawValue)) { - return rawValue; - } - var ref = {}; - def(ref, RefFlag, true); - def(ref, "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */, shallow); - def(ref, 'dep', defineReactive(ref, 'value', rawValue, null, shallow, isServerRendering())); - return ref; - } - function triggerRef(ref) { - if (!ref.dep) { - warn$2("received object is not a triggerable ref."); - } - { - ref.dep && - ref.dep.notify({ - type: "set" /* TriggerOpTypes.SET */, - target: ref, - key: 'value' - }); - } - } - function unref(ref) { - return isRef(ref) ? ref.value : ref; - } - function proxyRefs(objectWithRefs) { - if (isReactive(objectWithRefs)) { - return objectWithRefs; - } - var proxy = {}; - var keys = Object.keys(objectWithRefs); - for (var i = 0; i < keys.length; i++) { - proxyWithRefUnwrap(proxy, objectWithRefs, keys[i]); - } - return proxy; - } - function proxyWithRefUnwrap(target, source, key) { - Object.defineProperty(target, key, { - enumerable: true, - configurable: true, - get: function () { - var val = source[key]; - if (isRef(val)) { - return val.value; - } - else { - var ob = val && val.__ob__; - if (ob) - ob.dep.depend(); - return val; - } - }, - set: function (value) { - var oldValue = source[key]; - if (isRef(oldValue) && !isRef(value)) { - oldValue.value = value; - } - else { - source[key] = value; - } - } - }); - } - function customRef(factory) { - var dep = new Dep(); - var _a = factory(function () { - { - dep.depend({ - target: ref, - type: "get" /* TrackOpTypes.GET */, - key: 'value' - }); - } - }, function () { - { - dep.notify({ - target: ref, - type: "set" /* TriggerOpTypes.SET */, - key: 'value' - }); - } - }), get = _a.get, set = _a.set; - var ref = { - get value() { - return get(); - }, - set value(newVal) { - set(newVal); - } - }; - def(ref, RefFlag, true); - return ref; - } - function toRefs(object) { - if (!isReactive(object)) { - warn$2("toRefs() expects a reactive object but received a plain one."); - } - var ret = isArray(object) ? new Array(object.length) : {}; - for (var key in object) { - ret[key] = toRef(object, key); - } - return ret; - } - function toRef(object, key, defaultValue) { - var val = object[key]; - if (isRef(val)) { - return val; - } - var ref = { - get value() { - var val = object[key]; - return val === undefined ? defaultValue : val; - }, - set value(newVal) { - object[key] = newVal; - } - }; - def(ref, RefFlag, true); - return ref; - } + const HTML_TAGS = "html,body,base,head,link,meta,style,title,address,article,aside,footer,header,hgroup,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,summary,template,blockquote,iframe,tfoot"; + const SVG_TAGS = "svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,feDistantLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,text,textPath,title,tspan,unknown,use,view"; + const MATH_TAGS = "annotation,annotation-xml,maction,maligngroup,malignmark,math,menclose,merror,mfenced,mfrac,mfraction,mglyph,mi,mlabeledtr,mlongdiv,mmultiscripts,mn,mo,mover,mpadded,mphantom,mprescripts,mroot,mrow,ms,mscarries,mscarry,msgroup,msline,mspace,msqrt,msrow,mstack,mstyle,msub,msubsup,msup,mtable,mtd,mtext,mtr,munder,munderover,none,semantics"; + const VOID_TAGS = "area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr"; + const isHTMLTag = /* @__PURE__ */ makeMap(HTML_TAGS); + const isSVGTag = /* @__PURE__ */ makeMap(SVG_TAGS); + const isMathMLTag = /* @__PURE__ */ makeMap(MATH_TAGS); + const isVoidTag = /* @__PURE__ */ makeMap(VOID_TAGS); - var rawToReadonlyFlag = "__v_rawToReadonly"; - var rawToShallowReadonlyFlag = "__v_rawToShallowReadonly"; - function readonly(target) { - return createReadonly(target, false); + const specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`; + const isSpecialBooleanAttr = /* @__PURE__ */ makeMap(specialBooleanAttrs); + const isBooleanAttr = /* @__PURE__ */ makeMap( + specialBooleanAttrs + `,async,autofocus,autoplay,controls,default,defer,disabled,hidden,inert,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected` + ); + function includeBooleanAttr(value) { + return !!value || value === ""; } - function createReadonly(target, shallow) { - if (!isPlainObject(target)) { - { - if (isArray(target)) { - warn$2("Vue 2 does not support readonly arrays."); - } - else if (isCollectionType(target)) { - warn$2("Vue 2 does not support readonly collection types such as Map or Set."); - } - else { - warn$2("value cannot be made readonly: ".concat(typeof target)); - } - } - return target; - } - if (!Object.isExtensible(target)) { - warn$2("Vue 2 does not support creating readonly proxy for non-extensible object."); - } - // already a readonly object - if (isReadonly(target)) { - return target; - } - // already has a readonly proxy - var existingFlag = shallow ? rawToShallowReadonlyFlag : rawToReadonlyFlag; - var existingProxy = target[existingFlag]; - if (existingProxy) { - return existingProxy; - } - var proxy = Object.create(Object.getPrototypeOf(target)); - def(target, existingFlag, proxy); - def(proxy, "__v_isReadonly" /* ReactiveFlags.IS_READONLY */, true); - def(proxy, "__v_raw" /* ReactiveFlags.RAW */, target); - if (isRef(target)) { - def(proxy, RefFlag, true); - } - if (shallow || isShallow(target)) { - def(proxy, "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */, true); - } - var keys = Object.keys(target); - for (var i = 0; i < keys.length; i++) { - defineReadonlyProperty(proxy, target, keys[i], shallow); - } - return proxy; - } - function defineReadonlyProperty(proxy, target, key, shallow) { - Object.defineProperty(proxy, key, { - enumerable: true, - configurable: true, - get: function () { - var val = target[key]; - return shallow || !isPlainObject(val) ? val : readonly(val); - }, - set: function () { - warn$2("Set operation on key \"".concat(key, "\" failed: target is readonly.")); - } - }); - } - /** - * Returns a reactive-copy of the original object, where only the root level - * properties are readonly, and does NOT unwrap refs nor recursively convert - * returned properties. - * This is used for creating the props proxy object for stateful components. - */ - function shallowReadonly(target) { - return createReadonly(target, true); - } - - function computed(getterOrOptions, debugOptions) { - var getter; - var setter; - var onlyGetter = isFunction(getterOrOptions); - if (onlyGetter) { - getter = getterOrOptions; - setter = function () { - warn$2('Write operation failed: computed value is readonly'); - } - ; - } - else { - getter = getterOrOptions.get; - setter = getterOrOptions.set; - } - var watcher = isServerRendering() - ? null - : new Watcher(currentInstance, getter, noop, { lazy: true }); - if (watcher && debugOptions) { - watcher.onTrack = debugOptions.onTrack; - watcher.onTrigger = debugOptions.onTrigger; - } - var ref = { - // some libs rely on the presence effect for checking computed refs - // from normal refs, but the implementation doesn't matter - effect: watcher, - get value() { - if (watcher) { - if (watcher.dirty) { - watcher.evaluate(); - } - if (Dep.target) { - if (Dep.target.onTrack) { - Dep.target.onTrack({ - effect: Dep.target, - target: ref, - type: "get" /* TrackOpTypes.GET */, - key: 'value' - }); - } - watcher.depend(); - } - return watcher.value; - } - else { - return getter(); - } - }, - set value(newVal) { - setter(newVal); - } - }; - def(ref, RefFlag, true); - def(ref, "__v_isReadonly" /* ReactiveFlags.IS_READONLY */, onlyGetter); - return ref; - } - - var mark; - var measure; - { - var perf_1 = inBrowser && window.performance; - /* istanbul ignore if */ - if (perf_1 && - // @ts-ignore - perf_1.mark && - // @ts-ignore - perf_1.measure && - // @ts-ignore - perf_1.clearMarks && - // @ts-ignore - perf_1.clearMeasures) { - mark = function (tag) { return perf_1.mark(tag); }; - measure = function (name, startTag, endTag) { - perf_1.measure(name, startTag, endTag); - perf_1.clearMarks(startTag); - perf_1.clearMarks(endTag); - // perf.clearMeasures(name) - }; - } - } - - var normalizeEvent = cached(function (name) { - var passive = name.charAt(0) === '&'; - name = passive ? name.slice(1) : name; - var once = name.charAt(0) === '~'; // Prefixed last, checked first - name = once ? name.slice(1) : name; - var capture = name.charAt(0) === '!'; - name = capture ? name.slice(1) : name; - return { - name: name, - once: once, - capture: capture, - passive: passive - }; - }); - function createFnInvoker(fns, vm) { - function invoker() { - var fns = invoker.fns; - if (isArray(fns)) { - var cloned = fns.slice(); - for (var i = 0; i < cloned.length; i++) { - invokeWithErrorHandling(cloned[i], null, arguments, vm, "v-on handler"); - } - } - else { - // return handler return value for single handlers - return invokeWithErrorHandling(fns, null, arguments, vm, "v-on handler"); - } - } - invoker.fns = fns; - return invoker; - } - function updateListeners(on, oldOn, add, remove, createOnceHandler, vm) { - var name, cur, old, event; - for (name in on) { - cur = on[name]; - old = oldOn[name]; - event = normalizeEvent(name); - if (isUndef(cur)) { - warn$2("Invalid handler for event \"".concat(event.name, "\": got ") + String(cur), vm); - } - else if (isUndef(old)) { - if (isUndef(cur.fns)) { - cur = on[name] = createFnInvoker(cur, vm); - } - if (isTrue(event.once)) { - cur = on[name] = createOnceHandler(event.name, cur, event.capture); - } - add(event.name, cur, event.capture, event.passive, event.params); - } - else if (cur !== old) { - old.fns = cur; - on[name] = old; - } - } - for (name in oldOn) { - if (isUndef(on[name])) { - event = normalizeEvent(name); - remove(event.name, oldOn[name], event.capture); - } - } - } - - function mergeVNodeHook(def, hookKey, hook) { - if (def instanceof VNode) { - def = def.data.hook || (def.data.hook = {}); - } - var invoker; - var oldHook = def[hookKey]; - function wrappedHook() { - hook.apply(this, arguments); - // important: remove merged hook to ensure it's called only once - // and prevent memory leak - remove$2(invoker.fns, wrappedHook); - } - if (isUndef(oldHook)) { - // no existing hook - invoker = createFnInvoker([wrappedHook]); - } - else { - /* istanbul ignore if */ - if (isDef(oldHook.fns) && isTrue(oldHook.merged)) { - // already a merged invoker - invoker = oldHook; - invoker.fns.push(wrappedHook); - } - else { - // existing plain hook - invoker = createFnInvoker([oldHook, wrappedHook]); - } - } - invoker.merged = true; - def[hookKey] = invoker; - } - - function extractPropsFromVNodeData(data, Ctor, tag) { - // we are only extracting raw values here. - // validation and default values are handled in the child - // component itself. - var propOptions = Ctor.options.props; - if (isUndef(propOptions)) { - return; - } - var res = {}; - var attrs = data.attrs, props = data.props; - if (isDef(attrs) || isDef(props)) { - for (var key in propOptions) { - var altKey = hyphenate(key); - { - var keyInLowerCase = key.toLowerCase(); - if (key !== keyInLowerCase && attrs && hasOwn(attrs, keyInLowerCase)) { - tip("Prop \"".concat(keyInLowerCase, "\" is passed to component ") + - "".concat(formatComponentName( - // @ts-expect-error tag is string - tag || Ctor), ", but the declared prop name is") + - " \"".concat(key, "\". ") + - "Note that HTML attributes are case-insensitive and camelCased " + - "props need to use their kebab-case equivalents when using in-DOM " + - "templates. You should probably use \"".concat(altKey, "\" instead of \"").concat(key, "\".")); - } - } - checkProp(res, props, key, altKey, true) || - checkProp(res, attrs, key, altKey, false); - } - } - return res; - } - function checkProp(res, hash, key, altKey, preserve) { - if (isDef(hash)) { - if (hasOwn(hash, key)) { - res[key] = hash[key]; - if (!preserve) { - delete hash[key]; - } - return true; - } - else if (hasOwn(hash, altKey)) { - res[key] = hash[altKey]; - if (!preserve) { - delete hash[altKey]; - } - return true; - } - } + const isKnownHtmlAttr = /* @__PURE__ */ makeMap( + `accept,accept-charset,accesskey,action,align,allow,alt,async,autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,border,buffered,capture,challenge,charset,checked,cite,class,code,codebase,color,cols,colspan,content,contenteditable,contextmenu,controls,coords,crossorigin,csp,data,datetime,decoding,default,defer,dir,dirname,disabled,download,draggable,dropzone,enctype,enterkeyhint,for,form,formaction,formenctype,formmethod,formnovalidate,formtarget,headers,height,hidden,high,href,hreflang,http-equiv,icon,id,importance,inert,integrity,ismap,itemprop,keytype,kind,label,lang,language,loading,list,loop,low,manifest,max,maxlength,minlength,media,min,multiple,muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,preload,radiogroup,readonly,referrerpolicy,rel,required,reversed,rows,rowspan,sandbox,scope,scoped,selected,shape,size,sizes,slot,span,spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,target,title,translate,type,usemap,value,width,wrap` + ); + const isKnownSvgAttr = /* @__PURE__ */ makeMap( + `xmlns,accent-height,accumulate,additive,alignment-baseline,alphabetic,amplitude,arabic-form,ascent,attributeName,attributeType,azimuth,baseFrequency,baseline-shift,baseProfile,bbox,begin,bias,by,calcMode,cap-height,class,clip,clipPathUnits,clip-path,clip-rule,color,color-interpolation,color-interpolation-filters,color-profile,color-rendering,contentScriptType,contentStyleType,crossorigin,cursor,cx,cy,d,decelerate,descent,diffuseConstant,direction,display,divisor,dominant-baseline,dur,dx,dy,edgeMode,elevation,enable-background,end,exponent,fill,fill-opacity,fill-rule,filter,filterRes,filterUnits,flood-color,flood-opacity,font-family,font-size,font-size-adjust,font-stretch,font-style,font-variant,font-weight,format,from,fr,fx,fy,g1,g2,glyph-name,glyph-orientation-horizontal,glyph-orientation-vertical,glyphRef,gradientTransform,gradientUnits,hanging,height,href,hreflang,horiz-adv-x,horiz-origin-x,id,ideographic,image-rendering,in,in2,intercept,k,k1,k2,k3,k4,kernelMatrix,kernelUnitLength,kerning,keyPoints,keySplines,keyTimes,lang,lengthAdjust,letter-spacing,lighting-color,limitingConeAngle,local,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mask,maskContentUnits,maskUnits,mathematical,max,media,method,min,mode,name,numOctaves,offset,opacity,operator,order,orient,orientation,origin,overflow,overline-position,overline-thickness,panose-1,paint-order,path,pathLength,patternContentUnits,patternTransform,patternUnits,ping,pointer-events,points,pointsAtX,pointsAtY,pointsAtZ,preserveAlpha,preserveAspectRatio,primitiveUnits,r,radius,referrerPolicy,refX,refY,rel,rendering-intent,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,result,rotate,rx,ry,scale,seed,shape-rendering,slope,spacing,specularConstant,specularExponent,speed,spreadMethod,startOffset,stdDeviation,stemh,stemv,stitchTiles,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,string,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,style,surfaceScale,systemLanguage,tabindex,tableValues,target,targetX,targetY,text-anchor,text-decoration,text-rendering,textLength,to,transform,transform-origin,type,u1,u2,underline-position,underline-thickness,unicode,unicode-bidi,unicode-range,units-per-em,v-alphabetic,v-hanging,v-ideographic,v-mathematical,values,vector-effect,version,vert-adv-y,vert-origin-x,vert-origin-y,viewBox,viewTarget,visibility,width,widths,word-spacing,writing-mode,x,x-height,x1,x2,xChannelSelector,xlink:actuate,xlink:arcrole,xlink:href,xlink:role,xlink:show,xlink:title,xlink:type,xmlns:xlink,xml:base,xml:lang,xml:space,y,y1,y2,yChannelSelector,z,zoomAndPan` + ); + function isRenderableAttrValue(value) { + if (value == null) { return false; + } + const type = typeof value; + return type === "string" || type === "number" || type === "boolean"; } - // The template compiler attempts to minimize the need for normalization by - // statically analyzing the template at compile time. - // - // For plain HTML markup, normalization can be completely skipped because the - // generated render function is guaranteed to return Array. There are - // two cases where extra normalization is needed: - // 1. When the children contains components - because a functional component - // may return an Array instead of a single root. In this case, just a simple - // normalization is needed - if any child is an Array, we flatten the whole - // thing with Array.prototype.concat. It is guaranteed to be only 1-level deep - // because functional components already normalize their own children. - function simpleNormalizeChildren(children) { - for (var i = 0; i < children.length; i++) { - if (isArray(children[i])) { - return Array.prototype.concat.apply([], children); - } - } - return children; - } - // 2. When the children contains constructs that always generated nested Arrays, - // e.g.