feat(ota): add ota page and api, add direct link update
This commit is contained in:
parent
fb833e6af7
commit
11b53e7531
|
@ -12,6 +12,7 @@ import {routeCtrlMsg, routeModuleServerMsg} from "@/router/msgRouter";
|
||||||
import {globalNotify} from "@/composables/notification";
|
import {globalNotify} from "@/composables/notification";
|
||||||
import {isDevMode} from "@/composables/buildMode";
|
import {isDevMode} from "@/composables/buildMode";
|
||||||
import {ElMessageBox} from "element-plus";
|
import {ElMessageBox} from "element-plus";
|
||||||
|
import {useSystemModule} from "@/composables/useSystemModule";
|
||||||
|
|
||||||
const wsState = useWsStore();
|
const wsState = useWsStore();
|
||||||
|
|
||||||
|
@ -48,9 +49,7 @@ onMounted(() => {
|
||||||
websocketService = getWebsocketService();
|
websocketService = getWebsocketService();
|
||||||
websocketService.init(host, onServerMsg, onClientCtrl);
|
websocketService.init(host, onServerMsg, onClientCtrl);
|
||||||
changeFavicon();
|
changeFavicon();
|
||||||
ElMessageBox.alert('欢迎参与允斯无线串口助手固件内侧,有任何问题请在Q群踢群主:642246000', '2024-05-24', {
|
useSystemModule();
|
||||||
confirmButtonText: '好的',
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
import {type ApiJsonMsg, sendJsonMsg, WtModuleID} from '@/api'
|
||||||
|
|
||||||
|
export enum WtOTACmd {
|
||||||
|
WT_OTA_GET_UPDATE_INFO = 1, /* total_size, ver */
|
||||||
|
WT_OTA_DO_UPDATE = 2, /* returns OK, chunk of remaining bytes and total length -> wt_event_manager */
|
||||||
|
WT_OTA_GET_PROGRESS = 3, /* returns chunk of remaining bytes and total length */
|
||||||
|
WT_OTA_DO_URL_UPDATE = 4, /* force update { url: "https://" } */
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum WtOTAProgressStatus {
|
||||||
|
OK = "OK",
|
||||||
|
IDLE = "IDLE",
|
||||||
|
IN_PROGRESS = "IN_PROGRESS",
|
||||||
|
FAILED = "FAILED",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IOTAProgress extends ApiJsonMsg {
|
||||||
|
progress: number;
|
||||||
|
total_size: number;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IOTAFmInfo extends ApiJsonMsg {
|
||||||
|
fm_size: number;
|
||||||
|
fm_ver: string;
|
||||||
|
upd_date: string;
|
||||||
|
upd_note: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function wt_ota_get_update_info() {
|
||||||
|
const msg: ApiJsonMsg = {
|
||||||
|
module: WtModuleID.OTA,
|
||||||
|
cmd: WtOTACmd.WT_OTA_GET_UPDATE_INFO,
|
||||||
|
};
|
||||||
|
sendJsonMsg(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function wt_ota_do_update() {
|
||||||
|
const msg: ApiJsonMsg = {
|
||||||
|
module: WtModuleID.OTA,
|
||||||
|
cmd: WtOTACmd.WT_OTA_DO_UPDATE,
|
||||||
|
};
|
||||||
|
sendJsonMsg(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function wt_ota_get_progress() {
|
||||||
|
const msg: ApiJsonMsg = {
|
||||||
|
module: WtModuleID.OTA,
|
||||||
|
cmd: WtOTACmd.WT_OTA_GET_PROGRESS,
|
||||||
|
};
|
||||||
|
sendJsonMsg(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function wt_ota_do_url_update(url: string) {
|
||||||
|
const msg: ApiJsonMsg & {url: string} = {
|
||||||
|
module: WtModuleID.OTA,
|
||||||
|
cmd: WtOTACmd.WT_OTA_DO_URL_UPDATE,
|
||||||
|
url: url,
|
||||||
|
};
|
||||||
|
sendJsonMsg(msg);
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
import {type ApiJsonMsg, sendJsonMsg, WtModuleID} from '@/api'
|
||||||
|
|
||||||
|
export enum WtSytemCmd {
|
||||||
|
WT_SYS_GET_FM_INFO = 1,
|
||||||
|
WT_SYS_REBOOT = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISysFmInfo extends ApiJsonMsg {
|
||||||
|
fm_ver: string;
|
||||||
|
upd_date: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISysHwInfo extends ApiJsonMsg {
|
||||||
|
hw_ver: string;
|
||||||
|
mf_date: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function wt_sys_get_fm_info() {
|
||||||
|
const msg: ApiJsonMsg = {
|
||||||
|
module: WtModuleID.SYSTEM,
|
||||||
|
cmd: WtSytemCmd.WT_SYS_GET_FM_INFO,
|
||||||
|
};
|
||||||
|
sendJsonMsg(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function wt_sys_reboot() {
|
||||||
|
const msg: ApiJsonMsg = {
|
||||||
|
module: WtModuleID.SYSTEM,
|
||||||
|
cmd: WtSytemCmd.WT_SYS_REBOOT,
|
||||||
|
};
|
||||||
|
sendJsonMsg(msg);
|
||||||
|
}
|
|
@ -34,6 +34,8 @@ export enum WtModuleID {
|
||||||
WIFI = 1,
|
WIFI = 1,
|
||||||
DATA_FLOW = 2,
|
DATA_FLOW = 2,
|
||||||
UART = 4,
|
UART = 4,
|
||||||
|
OTA = 5,
|
||||||
|
SYSTEM = 6,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sendJsonMsg(apiJsonMsg: ApiJsonMsg) {
|
export function sendJsonMsg(apiJsonMsg: ApiJsonMsg) {
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
import {useSystemStore} from "@/stores/useSystemStore";
|
||||||
|
import {registerModule} from "@/router/msgRouter";
|
||||||
|
import {type ApiJsonMsg, ControlEvent, type ControlMsg, ControlMsgType, WtModuleID} from "@/api";
|
||||||
|
import {type ISysFmInfo, wt_sys_get_fm_info, WtSytemCmd} from "@/api/apiSystem";
|
||||||
|
|
||||||
|
|
||||||
|
export function useSystemModule() {
|
||||||
|
const sysStore = useSystemStore()
|
||||||
|
|
||||||
|
function onClientCtrl(msg: ControlMsg) {
|
||||||
|
if (msg.type !== ControlMsgType.WS_EVENT) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.data === ControlEvent.CONNECTED) {
|
||||||
|
wt_sys_get_fm_info();
|
||||||
|
sysStore.rebootInProgress = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClientMsg(msg: ApiJsonMsg) {
|
||||||
|
switch (msg.cmd as WtSytemCmd) {
|
||||||
|
case WtSytemCmd.WT_SYS_REBOOT:
|
||||||
|
sysStore.rebootInProgress = true;
|
||||||
|
break;
|
||||||
|
case WtSytemCmd.WT_SYS_GET_FM_INFO: {
|
||||||
|
const fm_info = msg as ISysFmInfo;
|
||||||
|
sysStore.curFmInfo.date = fm_info.upd_date;
|
||||||
|
sysStore.curFmInfo.ver = fm_info.fm_ver;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
registerModule(WtModuleID.SYSTEM, {
|
||||||
|
ctrlCallback: onClientCtrl,
|
||||||
|
serverJsonMsgCallback: onClientMsg,
|
||||||
|
serverBinMsgCallback: () => {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,5 +16,6 @@ export default {
|
||||||
uart: "UART透传",
|
uart: "UART透传",
|
||||||
feedback: "反馈",
|
feedback: "反馈",
|
||||||
close: "关闭",
|
close: "关闭",
|
||||||
|
update: "更新",
|
||||||
},
|
},
|
||||||
}
|
}
|
|
@ -5,6 +5,7 @@ import Feedback from '@/views/Feedback.vue'
|
||||||
import About from '@/views/About.vue'
|
import About from '@/views/About.vue'
|
||||||
import Uart from '@/views/Uart.vue'
|
import Uart from '@/views/Uart.vue'
|
||||||
import Page404 from '@/views/404.vue'
|
import Page404 from '@/views/404.vue'
|
||||||
|
import Update from '@/views/Update.vue'
|
||||||
import {translate} from "@/locales";
|
import {translate} from "@/locales";
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,7 +39,12 @@ const router = createRouter({
|
||||||
meta: {title: translate('page.feedback')},
|
meta: {title: translate('page.feedback')},
|
||||||
name: 'feedback',
|
name: 'feedback',
|
||||||
component: Feedback,
|
component: Feedback,
|
||||||
}, {
|
}, {
|
||||||
|
path: '/update:ext(.*)',
|
||||||
|
meta: {title: translate('page.update')},
|
||||||
|
name: 'update',
|
||||||
|
component: Update,
|
||||||
|
}, {
|
||||||
path: '/:catchAll(.*)', // This will match all paths that aren't matched by above routes
|
path: '/:catchAll(.*)', // This will match all paths that aren't matched by above routes
|
||||||
name: 'NotFound',
|
name: 'NotFound',
|
||||||
component: Page404,
|
component: Page404,
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import {defineStore} from "pinia";
|
||||||
|
import {ref} from "vue";
|
||||||
|
|
||||||
|
export const useSystemStore = defineStore('system', () => {
|
||||||
|
|
||||||
|
const curFmInfo = ref({
|
||||||
|
ver: "-",
|
||||||
|
date: "-",
|
||||||
|
});
|
||||||
|
|
||||||
|
const hwInfo = ref({
|
||||||
|
ver: "-",
|
||||||
|
date: "-",
|
||||||
|
})
|
||||||
|
|
||||||
|
const rebootInProgress = ref(false);
|
||||||
|
|
||||||
|
return {
|
||||||
|
curFmInfo,
|
||||||
|
hwInfo,
|
||||||
|
rebootInProgress,
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,6 +1,9 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import {useSystemStore} from "@/stores/useSystemStore";
|
||||||
|
|
||||||
const version = import.meta.env.VITE_APP_GIT_TAG || "v0.0.0";
|
const version = import.meta.env.VITE_APP_GIT_TAG || "v0.0.0";
|
||||||
const compileTime = import.meta.env.VITE_APP_LAST_COMMIT || "1970-00-00";
|
const compileTime = import.meta.env.VITE_APP_LAST_COMMIT || "1970-00-00";
|
||||||
|
const sysStore = useSystemStore();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -40,10 +43,11 @@ const compileTime = import.meta.env.VITE_APP_LAST_COMMIT || "1970-00-00";
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
<el-collapse-item title="关于下位机">
|
<el-collapse-item title="关于调试器">
|
||||||
<el-descriptions border :column="1" class="mt-5 description-style">
|
<el-descriptions border :column="1" class="mt-5 description-style">
|
||||||
<el-descriptions-item label="官网"><a target="_blank" href="https://yunsi.studio/wireless-proxy">允斯工作室</a></el-descriptions-item>
|
<el-descriptions-item label="官网"><a target="_blank" href="https://yunsi.studio/wireless-debugger">https://yunsi.studio/wireless-debugger</a></el-descriptions-item>
|
||||||
<el-descriptions-item label="版本">-</el-descriptions-item>
|
<el-descriptions-item label="版本">{{ sysStore.curFmInfo.ver }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="更新日期">{{ sysStore.curFmInfo.date }}</el-descriptions-item>
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
|
|
||||||
<el-descriptions title="鸣谢" border :column="1" class="mt-5 description-style">
|
<el-descriptions title="鸣谢" border :column="1" class="mt-5 description-style">
|
||||||
|
|
|
@ -0,0 +1,214 @@
|
||||||
|
<template>
|
||||||
|
<div class="text-layout description-style">
|
||||||
|
<h1 class="page-title">
|
||||||
|
固件更新
|
||||||
|
</h1>
|
||||||
|
<p class="text-center">(需联网)</p>
|
||||||
|
<el-divider></el-divider>
|
||||||
|
|
||||||
|
<el-descriptions title="当前版本" border :column="1">
|
||||||
|
<el-descriptions-item label="硬件版本">{{ sysStore.hwInfo.ver }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="固件版本">{{ sysStore.curFmInfo.ver }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="固件日期">{{ sysStore.curFmInfo.date }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
|
||||||
|
<el-divider></el-divider>
|
||||||
|
|
||||||
|
<el-descriptions title="最新版本" border :column="1">
|
||||||
|
<template #extra>
|
||||||
|
<div class="flex">
|
||||||
|
<el-tooltip placement="top" effect="light">
|
||||||
|
<template #content>
|
||||||
|
<p>2秒延迟后重启</p>
|
||||||
|
</template>
|
||||||
|
<el-button @click="doReboot" type="warning" :disabled="sysStore.rebootInProgress">
|
||||||
|
重启{{ sysStore.rebootInProgress ? '中' : ''}}
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
|
||||||
|
<el-button @click="doUpdate" type="primary" :disabled="!canUpdate">
|
||||||
|
更新
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<el-descriptions-item label="固件版本">{{ newFmInfo.fm_ver }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="更新日期">{{ newFmInfo.upd_date }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="固件大小">{{ newFmInfo.fm_size }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="更新进度">
|
||||||
|
<el-alert v-if="updateStatus === 'OK'" title="更新已完成,重启后,刷新网页生效" type="success" show-icon :closable="false" />
|
||||||
|
<el-progress v-else :percentage="updateProgress" :format="format" :status="progressBarStatus"/>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="更新内容">
|
||||||
|
<pre>{{ newFmInfo.upd_note }}</pre>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
|
||||||
|
<el-divider @click="showHidden = !showHidden">底部</el-divider>
|
||||||
|
<div v-if="showHidden">
|
||||||
|
<p>直链更新(仅用于测试,请勿使用)</p>
|
||||||
|
<el-input placeholder="https://..." v-model="directLinkUpdate"></el-input>
|
||||||
|
<el-button type="primary" @click="doDirectLinkUpdate">更新</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {onMounted, onUnmounted, ref} from "vue";
|
||||||
|
import type {ApiJsonMsg, ControlMsg} from "@/api";
|
||||||
|
import {
|
||||||
|
type IOTAFmInfo,
|
||||||
|
type IOTAProgress,
|
||||||
|
wt_ota_do_update, wt_ota_do_url_update,
|
||||||
|
wt_ota_get_progress,
|
||||||
|
wt_ota_get_update_info,
|
||||||
|
WtOTACmd, WtOTAProgressStatus
|
||||||
|
} from "@/api/apiOTA";
|
||||||
|
import {ControlEvent, ControlMsgType, WtModuleID} from "@/api";
|
||||||
|
import {registerModule, unregisterModule} from "@/router/msgRouter";
|
||||||
|
import {useSystemStore} from "@/stores/useSystemStore";
|
||||||
|
import {wt_sys_reboot} from "@/api/apiSystem";
|
||||||
|
|
||||||
|
const sysStore = useSystemStore();
|
||||||
|
const showHidden = ref(false)
|
||||||
|
|
||||||
|
const format = (percentage: number) => (percentage.toFixed(2) + '%')
|
||||||
|
|
||||||
|
const canUpdate = ref(false);
|
||||||
|
const updateProgress = ref(0);
|
||||||
|
const updateStatus = ref('');
|
||||||
|
|
||||||
|
const progressBarStatus = ref('');
|
||||||
|
|
||||||
|
const directLinkUpdate = ref("");
|
||||||
|
|
||||||
|
let progressIntervalID = -1;
|
||||||
|
|
||||||
|
const newFmInfo = ref({
|
||||||
|
fm_size: 0,
|
||||||
|
fm_ver: "-",
|
||||||
|
upd_date: "-",
|
||||||
|
upd_note: "-",
|
||||||
|
})
|
||||||
|
const onClientMsg = (msg: ApiJsonMsg) => {
|
||||||
|
switch (msg.cmd as WtOTACmd) {
|
||||||
|
case WtOTACmd.WT_OTA_GET_UPDATE_INFO: {
|
||||||
|
const info = msg as IOTAFmInfo;
|
||||||
|
Object.assign(newFmInfo.value, info);
|
||||||
|
if (newFmInfo.value.fm_ver !== sysStore.curFmInfo.ver && newFmInfo.value.fm_ver[0] !== '-'
|
||||||
|
&& updateStatus.value === 'IDLE') {
|
||||||
|
canUpdate.value = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WtOTACmd.WT_OTA_DO_UPDATE:
|
||||||
|
break;
|
||||||
|
case WtOTACmd.WT_OTA_GET_PROGRESS: {
|
||||||
|
const progress = msg as IOTAProgress;
|
||||||
|
updateStatus.value = progress.status;
|
||||||
|
if (progress.total_size !== 0) {
|
||||||
|
updateProgress.value = (progress.progress / progress.total_size) * 100;
|
||||||
|
} else {
|
||||||
|
updateProgress.value = 0;
|
||||||
|
}
|
||||||
|
if (progress.status === WtOTAProgressStatus.IDLE) {
|
||||||
|
if (newFmInfo.value.fm_ver !== sysStore.curFmInfo.ver && newFmInfo.value.fm_ver[0] !== '-') {
|
||||||
|
canUpdate.value = true;
|
||||||
|
}
|
||||||
|
if (progressIntervalID >= 0) {
|
||||||
|
clearInterval(progressIntervalID);
|
||||||
|
progressIntervalID = -1;
|
||||||
|
}
|
||||||
|
progressBarStatus.value = '';
|
||||||
|
} else if (progress.status === WtOTAProgressStatus.FAILED) {
|
||||||
|
if (progressIntervalID >= 0) {
|
||||||
|
clearInterval(progressIntervalID);
|
||||||
|
progressIntervalID = -1;
|
||||||
|
}
|
||||||
|
progressBarStatus.value = 'exception';
|
||||||
|
} else if (progress.status === WtOTAProgressStatus.IN_PROGRESS) {
|
||||||
|
if (progressIntervalID < 0) {
|
||||||
|
progressIntervalID = setInterval(() => {
|
||||||
|
wt_ota_get_progress();
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
progressBarStatus.value = '';
|
||||||
|
canUpdate.value = false;
|
||||||
|
} else if (progress.status === WtOTAProgressStatus.OK) {
|
||||||
|
if (progressIntervalID >= 0) {
|
||||||
|
clearInterval(progressIntervalID);
|
||||||
|
progressIntervalID = -1;
|
||||||
|
}
|
||||||
|
canUpdate.value = false;
|
||||||
|
progressBarStatus.value = 'success';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onClientCtrl = (msg: ControlMsg) => {
|
||||||
|
if (msg.type !== ControlMsgType.WS_EVENT) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.data === ControlEvent.CONNECTED) {
|
||||||
|
wt_ota_get_update_info();
|
||||||
|
wt_ota_get_progress();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function doUpdate() {
|
||||||
|
wt_ota_do_update();
|
||||||
|
progressIntervalID = setInterval(() => {
|
||||||
|
wt_ota_get_progress();
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function doReboot() {
|
||||||
|
wt_sys_reboot();
|
||||||
|
}
|
||||||
|
|
||||||
|
function doDirectLinkUpdate() {
|
||||||
|
if (directLinkUpdate.value.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
progressIntervalID = setInterval(() => {
|
||||||
|
wt_ota_get_progress();
|
||||||
|
}, 1000);
|
||||||
|
wt_ota_do_url_update(directLinkUpdate.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
registerModule(WtModuleID.OTA, {
|
||||||
|
ctrlCallback: onClientCtrl,
|
||||||
|
serverJsonMsgCallback: onClientMsg,
|
||||||
|
serverBinMsgCallback: () => {
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
wt_ota_get_update_info();
|
||||||
|
wt_ota_get_progress();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
unregisterModule(WtModuleID.OTA);
|
||||||
|
clearInterval(progressIntervalID);
|
||||||
|
progressIntervalID = -1;
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.description-style :deep(.el-descriptions__label) {
|
||||||
|
@apply w-32
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -67,7 +67,7 @@
|
||||||
|
|
||||||
<div class="flex flex-col justify-between m-4 mt-0">
|
<div class="flex flex-col justify-between m-4 mt-0">
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="(item, index) in menuItems" class="mb-1" :key="index">
|
<li v-for="(item, index) in sideBarItems" class="mb-1" :key="index">
|
||||||
<router-link @click="sideMenuOpen=false" :title="item.name" :to="item.href" :class="[sideMenuItemClass, item?.class]">{{ item.name }}</router-link>
|
<router-link @click="sideMenuOpen=false" :title="item.name" :to="item.href" :class="[sideMenuItemClass, item?.class]">{{ item.name }}</router-link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -147,10 +147,23 @@ type Item = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const menuItems: Item[] = ([
|
const menuItems: Item[] = ([
|
||||||
/* {
|
{
|
||||||
name: translate("page.home"),
|
name: translate("page.uart"),
|
||||||
href: "/",
|
href: "/uart",
|
||||||
}, */
|
}, {
|
||||||
|
name: translate("page.wifi"),
|
||||||
|
href: "/wifi",
|
||||||
|
}, {
|
||||||
|
name: translate("page.feedback"),
|
||||||
|
href: "/feedback",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const sideBarItems: Item[] = ([
|
||||||
|
/* {
|
||||||
|
name: translate("page.home"),
|
||||||
|
href: "/",
|
||||||
|
}, */
|
||||||
{
|
{
|
||||||
name: translate("page.uart"),
|
name: translate("page.uart"),
|
||||||
href: "/uart",
|
href: "/uart",
|
||||||
|
@ -163,6 +176,9 @@ const menuItems: Item[] = ([
|
||||||
}, {
|
}, {
|
||||||
name: translate("page.feedback"),
|
name: translate("page.feedback"),
|
||||||
href: "/feedback",
|
href: "/feedback",
|
||||||
|
}, {
|
||||||
|
name: translate("page.update"),
|
||||||
|
href: "/update",
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue