feat(uart) make settings independent between pages, and add enable checkbox
settings were synced between pages, now each pages can have different settings.
This commit is contained in:
parent
8e0d8234e5
commit
dd1b9adc0d
|
@ -8,7 +8,7 @@ import {
|
|||
watch,
|
||||
} from "vue";
|
||||
import {AnsiUp} from 'ansi_up'
|
||||
import {debouncedWatch, useStorage} from "@vueuse/core";
|
||||
import {debouncedWatch} from "@vueuse/core";
|
||||
import {type IUartConfig, uart_send_msg} from "@/api/apiUart";
|
||||
import {isDevMode} from "@/composables/buildMode";
|
||||
import {useUartStore} from "@/stores/useUartStore";
|
||||
|
@ -240,6 +240,44 @@ function generateBaudArr(results: { baud: number; }[]) {
|
|||
});
|
||||
}
|
||||
|
||||
export interface ISettings {
|
||||
testNumber: number;
|
||||
configTab: string;
|
||||
showText: boolean;
|
||||
showHex: boolean;
|
||||
showHexdump: boolean;
|
||||
showTimestamp: boolean;
|
||||
lineWrap: boolean;
|
||||
RxHexdumpColor: string;
|
||||
TxHexdumpColor: string;
|
||||
frameBreakSequence: string;
|
||||
frameBreakAfterSequence: boolean;
|
||||
frameBreakDelay: number;
|
||||
frameBreakSize: number;
|
||||
frameBreak: any[]; // Specify more precise types
|
||||
decodeANSI: boolean;
|
||||
frameFilterValue: string;
|
||||
autoUpdate: boolean;
|
||||
updateInterval: number;
|
||||
sendFramePrefix: string;
|
||||
sendFrameSuffix: string;
|
||||
loopSendInterval: number;
|
||||
sendBoxIsText: boolean;
|
||||
sendBox: string;
|
||||
winLeft: any;
|
||||
winRight: any;
|
||||
winAutoLayout: boolean;
|
||||
winLayoutMode: string;
|
||||
macroButtons: macroItem[];
|
||||
ipChangeAlert: boolean;
|
||||
}
|
||||
|
||||
interface macroItem {
|
||||
value: string;
|
||||
label: string;
|
||||
id: number;
|
||||
}
|
||||
|
||||
export const useDataViewerStore = defineStore('text-viewer', () => {
|
||||
const uartStore = useUartStore()
|
||||
|
||||
|
@ -270,10 +308,8 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
generateBaudArr(uartBaudList);
|
||||
|
||||
/* public value */
|
||||
const configPanelTab = useStorage("configTab" ,"second");
|
||||
const configPanelShow = ref(true);
|
||||
const quickAccessPanelShow = ref(true);
|
||||
const enableAnsiDecode = useStorage("decodeANSI", true);
|
||||
const configPanelTab = ref("second");
|
||||
const enableAnsiDecode = ref(true);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -283,12 +319,12 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
let RxSegment: Uint8Array = new Uint8Array(0);
|
||||
const RxRemainHexdump = ref("");
|
||||
|
||||
const frameBreakSequence = useStorage("frameBreakSequence", "\\n");
|
||||
const frameBreakAfterSequence = useStorage("frameBreakAfterSequence", true);
|
||||
const frameBreakSequence = ref("\\n");
|
||||
const frameBreakAfterSequence = ref(true);
|
||||
const frameBreakSequenceNormalized = computed(() => {
|
||||
return unescapeString(frameBreakSequence.value);
|
||||
});
|
||||
const frameBreakDelay = useStorage("frameBreakDelay", 0);
|
||||
const frameBreakDelay = ref(0);
|
||||
let frameBreakDelayTimeoutID: number = -1;
|
||||
|
||||
function frameBreakFlush() {
|
||||
|
@ -326,27 +362,24 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
|
||||
|
||||
|
||||
const frameBreakSize = useStorage("frameBreakSize", 0);
|
||||
const frameBreakRules = useStorage("breakRules", [{
|
||||
ref: frameBreakDelay,
|
||||
const frameBreakSize = ref(0);
|
||||
const frameBreakRules = ref([{
|
||||
name: '超时(ms)',
|
||||
type: 'number',
|
||||
min: -1,
|
||||
draggable: false,
|
||||
transformData: breakDelay,
|
||||
}, {
|
||||
ref: frameBreakSequence,
|
||||
name: '匹配',
|
||||
type: 'text',
|
||||
draggable: true,
|
||||
transformData: breakDelay,
|
||||
transformData: breakSequence,
|
||||
}, {
|
||||
ref: frameBreakSize,
|
||||
name: '字节(B)',
|
||||
type: 'number',
|
||||
min: 0,
|
||||
draggable: true,
|
||||
transformData: breakDelay,
|
||||
transformData: breakSize,
|
||||
},])
|
||||
|
||||
function breakDelay(inputArray: Uint8Array[]) {
|
||||
|
@ -406,19 +439,14 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
for (let i = 0; i < frameBreakRules.value.length; i++) {
|
||||
if (frameBreakRules.value[i].name === "超时(ms)") {
|
||||
frameBreakRules.value[i].transformData = breakDelay;
|
||||
frameBreakRules.value[i].ref = frameBreakDelay;
|
||||
} else if (frameBreakRules.value[i].name === "匹配") {
|
||||
frameBreakRules.value[i].transformData = breakSequence;
|
||||
frameBreakRules.value[i].ref = frameBreakSequence;
|
||||
} else {
|
||||
frameBreakRules.value[i].transformData = breakSize;
|
||||
frameBreakRules.value[i].ref = frameBreakSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reloadFrameBreak();
|
||||
|
||||
function addStringMessage(input: string, isRX: boolean, doSend: boolean = false) {
|
||||
const unescaped = unescapeString(input);
|
||||
addSegment(unescaped, isRX, doSend);
|
||||
|
@ -478,21 +506,20 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
RxRemainHexdump,
|
||||
addStringMessage,
|
||||
addSegment,
|
||||
reloadFrameBreak,
|
||||
}
|
||||
|
||||
const showText = useStorage('showText', true);
|
||||
const showHex = useStorage('showHex', false);
|
||||
const showHexdump = useStorage('showHexdump', false);
|
||||
const enableLineWrap = useStorage('lineWrap', false);
|
||||
const showTimestamp = useStorage('showTimestamp', true);
|
||||
const showText = ref(true);
|
||||
const showHex = ref(false);
|
||||
const showHexdump = ref(false);
|
||||
const enableLineWrap = ref(false);
|
||||
const showTimestamp = ref(true);
|
||||
const showVirtualScroll = ref(true);
|
||||
|
||||
const RxHexdumpColor = useStorage('RxHexdumpColor', "#f0f9eb");
|
||||
const RxHexdumpColor = ref("#f0f9eb");
|
||||
const RxTotalByteCount = ref(0);
|
||||
const RxByteCount = ref(0);
|
||||
|
||||
const TxHexdumpColor = useStorage('TxHexdumpColor', "#ecf4ff");
|
||||
const TxHexdumpColor = ref("#ecf4ff");
|
||||
const TxTotalByteCount = ref(0);
|
||||
const TxByteCount = ref(0);
|
||||
|
||||
|
@ -515,8 +542,8 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
const forceToBottom = ref(true);
|
||||
const filterChanged = ref(false);
|
||||
|
||||
const textPrefixValue = useStorage('sendFramePrefix', "");
|
||||
const textSuffixValue = useStorage('sendFrameSuffix', "\\r\\n");
|
||||
const textPrefixValue = ref("");
|
||||
const textSuffixValue = ref("\\r\\n");
|
||||
const hasAddedText = computed(() => {
|
||||
return textPrefixValue.value.length > 0 || textSuffixValue.value.length > 0;
|
||||
});
|
||||
|
@ -529,7 +556,7 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
stop_bits: 1,
|
||||
});
|
||||
|
||||
const filterValue = useStorage('frameFilterValue', '');
|
||||
const filterValue = ref('');
|
||||
const computedFilterValue = computed(() => {
|
||||
return unescapeString(filterValue.value);
|
||||
})
|
||||
|
@ -547,7 +574,7 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
|
||||
/* actual data shown on screen */
|
||||
const dataFiltered: ShallowReactive<IDataBuf[]> = shallowReactive([]);
|
||||
const dataFilterAutoUpdate = useStorage("autoUpdate", true);
|
||||
const dataFilterAutoUpdate = ref(true);
|
||||
const acceptIncomingData = ref(false);
|
||||
|
||||
// let frameBreakReady = false;
|
||||
|
@ -559,7 +586,7 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
}, {debounce: 300});
|
||||
|
||||
let batchDataUpdateIntervalID: number = -1;
|
||||
const batchUpdateTime = useStorage('updateInterval', 80); /* ms */
|
||||
const batchUpdateTime = ref(80); /* ms */
|
||||
let batchStartIndex: number = 0;
|
||||
|
||||
watch(batchUpdateTime, () => {
|
||||
|
@ -780,10 +807,10 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
|
||||
|
||||
const enableLoopSend = ref(false);
|
||||
const loopSendFreq = useStorage('loopSendInterval', 1000);
|
||||
const loopSendFreq = ref(1000);
|
||||
let loopSendIntervalID: number = -1;
|
||||
const uartInputTextBox = useStorage('sendBox', "");
|
||||
const isSendTextFormat = useStorage('sendBoxIsText', true);
|
||||
const sendBox = ref("");
|
||||
const sendBoxIsText = ref(true);
|
||||
const isHexStringValid = ref(false);
|
||||
|
||||
function loopSend() {
|
||||
|
@ -791,14 +818,14 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
enableLoopSend.value = false;
|
||||
}
|
||||
|
||||
if (isSendTextFormat.value) {
|
||||
addString(uartInputTextBox.value, false, true);
|
||||
if (sendBoxIsText.value) {
|
||||
addString(sendBox.value, false, true);
|
||||
} else {
|
||||
if (!isHexStringValid.value) {
|
||||
addString("HEX格式错误", false, false, 1);
|
||||
addHexString(uartInputTextBox.value, false, false, 1);
|
||||
addHexString(sendBox.value, false, false, 1);
|
||||
} else {
|
||||
addHexString(uartInputTextBox.value, false, true);
|
||||
addHexString(sendBox.value, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -829,8 +856,8 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
enableLoopSend,
|
||||
loopSendFreq,
|
||||
loopSendIntervalID,
|
||||
isSendTextFormat,
|
||||
uartInputTextBox,
|
||||
isSendTextFormat: sendBoxIsText,
|
||||
uartInputTextBox: sendBox,
|
||||
isHexStringValid,
|
||||
}
|
||||
|
||||
|
@ -842,7 +869,7 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
}
|
||||
|
||||
/* window layout */
|
||||
const winLeft = useStorage('winLeft',{
|
||||
const winLeft = ref({
|
||||
show: true,
|
||||
width: "100px",
|
||||
height: "100px",
|
||||
|
@ -850,15 +877,15 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
});
|
||||
|
||||
/* window layout */
|
||||
const winRight = useStorage('winRight',{
|
||||
const winRight = ref({
|
||||
show: true,
|
||||
width: "100px",
|
||||
height: "100px",
|
||||
borderSize: 3,
|
||||
});
|
||||
|
||||
const winAutoLayout = useStorage('winAuto', true);
|
||||
const winLayoutMode = useStorage('winLayout', 'row');
|
||||
const winAutoLayout = ref(true);
|
||||
const winLayoutMode = ref('row');
|
||||
|
||||
|
||||
const winLayoutRet = {
|
||||
|
@ -868,6 +895,204 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
winLayoutMode,
|
||||
}
|
||||
|
||||
/* macro buttons */
|
||||
|
||||
const macroData: Ref<macroItem[]> = ref([
|
||||
{
|
||||
value: 'AT',
|
||||
label: '测试AT',
|
||||
id: 1,
|
||||
},{
|
||||
value: 'AT+CSQ',
|
||||
label: '询信号强度',
|
||||
id: 2,
|
||||
},{
|
||||
value: 'AT+CGSN',
|
||||
label: '询序列号',
|
||||
id: 3,
|
||||
}, {
|
||||
value: 'AT+CGMR',
|
||||
label: '询固件版本',
|
||||
id: 4,
|
||||
}, {
|
||||
value: 'AT+CMEE',
|
||||
label: '询终端报错',
|
||||
id: 5,
|
||||
}, {
|
||||
value: 'AT+NRB',
|
||||
label: '重启',
|
||||
id: 6,
|
||||
}, {
|
||||
value: 'AT+CGATT',
|
||||
label: '询网络激活状态',
|
||||
id: 7,
|
||||
}, {
|
||||
value: 'AT+CEREG',
|
||||
label: '询网络注册状态',
|
||||
id: 8,
|
||||
}, {
|
||||
value: 'AT+CSCON',
|
||||
label: '询网络连接状态',
|
||||
id: 9,
|
||||
}
|
||||
]);
|
||||
const macroId = ref(10);
|
||||
|
||||
const macroDataRet = {
|
||||
macroData,
|
||||
macroId,
|
||||
}
|
||||
|
||||
|
||||
const autoSaveSettings = ref(true);
|
||||
/* save to localStorage */
|
||||
const testNumber = ref(0);
|
||||
const ipChangeAlert = ref(true);
|
||||
|
||||
const settings: Ref<ISettings> = ref({
|
||||
testNumber,
|
||||
macroButtons: macroData,
|
||||
|
||||
configTab: configPanelTab,
|
||||
showHex,
|
||||
showText,
|
||||
showHexdump,
|
||||
showTimestamp,
|
||||
lineWrap: enableLineWrap,
|
||||
RxHexdumpColor,
|
||||
TxHexdumpColor,
|
||||
|
||||
frameBreak: frameBreakRules,
|
||||
frameBreakSequence,
|
||||
frameBreakSize,
|
||||
frameBreakDelay,
|
||||
frameBreakAfterSequence,
|
||||
frameFilterValue: filterValue,
|
||||
decodeANSI: enableAnsiDecode,
|
||||
autoUpdate: dataFilterAutoUpdate,
|
||||
updateInterval: batchUpdateTime,
|
||||
sendFramePrefix: textPrefixValue,
|
||||
sendFrameSuffix: textSuffixValue,
|
||||
loopSendInterval: loopSendFreq,
|
||||
sendBoxIsText,
|
||||
sendBox,
|
||||
winRight,
|
||||
winLeft,
|
||||
winAutoLayout,
|
||||
winLayoutMode,
|
||||
ipChangeAlert,
|
||||
});
|
||||
|
||||
const settingsName = "uart-settings";
|
||||
|
||||
watch(() => settings, () => {
|
||||
if (autoSaveSettings.value) {
|
||||
localStorage.setItem(settingsName, JSON.stringify(settings.value));
|
||||
}
|
||||
}, {deep: true});
|
||||
|
||||
function loadSettings(settingsData: string = "") {
|
||||
let data: string | null = settingsData;
|
||||
if (settingsData === "") {
|
||||
data = localStorage.getItem(settingsName);
|
||||
}
|
||||
if (data) {
|
||||
// Assuming the stored data is a JSON string
|
||||
const parsedData = JSON.parse(data);
|
||||
if (parsedData.macroButtons !== undefined) {
|
||||
macroData.value = parsedData.macroButtons;
|
||||
}
|
||||
if (parsedData.configTab !== undefined) {
|
||||
configPanelTab.value = parsedData.configTab;
|
||||
}
|
||||
if (parsedData.showText !== undefined) {
|
||||
showText.value = parsedData.showText;
|
||||
}
|
||||
if (parsedData.showHex !== undefined) {
|
||||
showHex.value = parsedData.showHex;
|
||||
}
|
||||
if (parsedData.showHexdump !== undefined) {
|
||||
showHexdump.value = parsedData.showHexdump;
|
||||
}
|
||||
if (parsedData.showTimestamp !== undefined) {
|
||||
showTimestamp.value = parsedData.showTimestamp;
|
||||
}
|
||||
if (parsedData.lineWrap !== undefined) {
|
||||
enableLineWrap.value = parsedData.lineWrap;
|
||||
}
|
||||
if (parsedData.RxHexdumpColor !== undefined) {
|
||||
RxHexdumpColor.value = parsedData.RxHexdumpColor;
|
||||
}
|
||||
if (parsedData.TxHexdumpColor !== undefined) {
|
||||
TxHexdumpColor.value = parsedData.TxHexdumpColor;
|
||||
}
|
||||
if (parsedData.frameBreakSequence !== undefined) {
|
||||
frameBreakSequence.value = parsedData.frameBreakSequence;
|
||||
}
|
||||
if (parsedData.frameBreakAfterSequence !== undefined) {
|
||||
frameBreakAfterSequence.value = parsedData.frameBreakAfterSequence;
|
||||
}
|
||||
if (parsedData.frameBreakDelay !== undefined) {
|
||||
frameBreakDelay.value = parsedData.frameBreakDelay;
|
||||
}
|
||||
if (parsedData.frameBreakSize !== undefined) {
|
||||
frameBreakSize.value = parsedData.frameBreakSize;
|
||||
}
|
||||
|
||||
if (parsedData.frameBreak !== undefined) {
|
||||
frameBreakRules.value = parsedData.frameBreak;
|
||||
}
|
||||
if (parsedData.decodeANSI !== undefined) {
|
||||
enableAnsiDecode.value = parsedData.decodeANSI;
|
||||
}
|
||||
if (parsedData.frameFilterValue !== undefined) {
|
||||
filterValue.value = parsedData.frameFilterValue;
|
||||
}
|
||||
if (parsedData.autoUpdate !== undefined) {
|
||||
dataFilterAutoUpdate.value = parsedData.autoUpdate;
|
||||
}
|
||||
if (parsedData.updateInterval !== undefined) {
|
||||
batchUpdateTime.value = parsedData.updateInterval;
|
||||
}
|
||||
|
||||
if (parsedData.sendFramePrefix !== undefined) {
|
||||
textPrefixValue.value = parsedData.sendFramePrefix;
|
||||
}
|
||||
if (parsedData.sendFrameSuffix !== undefined) {
|
||||
textSuffixValue.value = parsedData.sendFrameSuffix;
|
||||
}
|
||||
|
||||
if (parsedData.loopSendInterval !== undefined) {
|
||||
loopSendFreq.value = parsedData.loopSendInterval;
|
||||
}
|
||||
if (parsedData.sendBoxIsText !== undefined) {
|
||||
sendBoxIsText.value = parsedData.sendBoxIsText;
|
||||
}
|
||||
if (parsedData.sendBox !== undefined) {
|
||||
sendBox.value = parsedData.sendBox;
|
||||
}
|
||||
|
||||
if (parsedData.winLeft !== undefined) {
|
||||
winLeft.value = parsedData.winLeft;
|
||||
}
|
||||
if (parsedData.winRight !== undefined) {
|
||||
winRight.value = parsedData.winRight;
|
||||
}
|
||||
if (parsedData.winAutoLayout !== undefined) {
|
||||
winAutoLayout.value = parsedData.winAutoLayout;
|
||||
}
|
||||
if (parsedData.winLayoutMode !== undefined) {
|
||||
winLayoutMode.value = parsedData.winLayoutMode;
|
||||
}
|
||||
if (parsedData.ipChangeAlert !== undefined) {
|
||||
ipChangeAlert.value = parsedData.ipChangeAlert;
|
||||
}
|
||||
|
||||
reloadFrameBreak();
|
||||
macroId.value = macroData.value.reduce((max, item) => Math.max(max, item.id), 0) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
addItem,
|
||||
addString,
|
||||
|
@ -882,8 +1107,6 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
clearByteCount,
|
||||
dataBufLength,
|
||||
configPanelTab,
|
||||
configPanelShow,
|
||||
quickAccessPanelShow,
|
||||
dataFiltered,
|
||||
dataFilterAutoUpdate,
|
||||
filterValue,
|
||||
|
@ -921,5 +1144,12 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
|||
setUartBaud,
|
||||
...loopSendRet,
|
||||
...winLayoutRet,
|
||||
...macroDataRet,
|
||||
|
||||
autoSaveSettings,
|
||||
settings,
|
||||
testNumber,
|
||||
loadSettings,
|
||||
ipChangeAlert,
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="button-m-0 messages-container flex flex-grow overflow-hidden" :class="{'flex-col': store.winLayoutMode ==='col'}">
|
||||
<div v-show="store.configPanelShow" ref="win1Ref" class="bg-gray-50 flex-shrink-0 overflow-auto"
|
||||
<div v-show="store.winLeft.show" ref="win1Ref" class="bg-gray-50 flex-shrink-0 overflow-auto"
|
||||
:class="{
|
||||
'max-w-60': store.winLayoutMode==='row', 'xl:max-w-80': store.winLayoutMode==='row',
|
||||
'min-w-60': store.winLayoutMode==='row', 'xl:min-w-80': store.winLayoutMode==='row'
|
||||
|
@ -9,7 +9,7 @@
|
|||
<text-data-config></text-data-config>
|
||||
</div>
|
||||
|
||||
<div v-show="store.configPanelShow && (winDataView.show || store.winRight.show)" ref="firstWinResizeRef"></div>
|
||||
<div v-show="store.winLeft.show && (winDataView.show || store.winRight.show)" ref="firstWinResizeRef"></div>
|
||||
|
||||
<div v-show="winDataView.show" class="flex flex-col flex-grow overflow-hidden p-2">
|
||||
<textDataViewer></textDataViewer>
|
||||
|
@ -40,7 +40,7 @@
|
|||
</div>
|
||||
<el-checkbox label="自适应" v-model="store.winAutoLayout" border size="small"
|
||||
:disabled="store.winLayoutMode==='col'"/>
|
||||
<el-checkbox label="设置窗" v-model="store.configPanelShow" border size="small" :disabled="store.winAutoLayout"/>
|
||||
<el-checkbox label="设置窗" v-model="store.winLeft.show" border size="small" :disabled="store.winAutoLayout"/>
|
||||
<el-checkbox label="数据窗" v-model="winDataView.show" border size="small" :disabled="store.winAutoLayout"/>
|
||||
<el-checkbox label="快捷窗" v-model="store.winRight.show" border size="small" :disabled="store.winAutoLayout"/>
|
||||
</div>
|
||||
|
@ -298,7 +298,7 @@ watch([
|
|||
() => store.winAutoLayout
|
||||
], (value) => {
|
||||
if (store.winAutoLayout) {
|
||||
store.configPanelShow = !value[0];
|
||||
store.winLeft.show = !value[0];
|
||||
win1Ref.value.style.minWidth = "";
|
||||
win1Ref.value.style.maxWidth = "";
|
||||
win2Ref.value.style.minWidth = "";
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<el-tab-pane label="接口" name="first" class="min-h-80">
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<el-form :size="store.configPanelShow ? '' : 'small'">
|
||||
<el-form :size="store.winLeft.show ? '' : 'small'">
|
||||
<el-form-item
|
||||
label="波特率"
|
||||
class="mb-2"
|
||||
|
@ -179,10 +179,11 @@
|
|||
<td :class="item.draggable ? 'sort-target' : ''">{{ item.name }}</td>
|
||||
<td>
|
||||
<div v-if="item.type === 'number'">
|
||||
<el-input-number v-model="item.ref" :min="item.min || 0" size="small" style="width: 100px"/>
|
||||
<el-input-number v-if="item.name === '超时(ms)'" v-model="store.frameBreakDelay" :min="item.min || 0" size="small" style="width: 100px"/>
|
||||
<el-input-number v-else v-model="store.frameBreakSize" :min="item.min || 0" size="small" style="width: 100px"/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-input class="break-input" v-model="item.ref" placeholder="文本;支持\n\x" size="small"
|
||||
<el-input class="break-input" v-model="store.frameBreakSequence" placeholder="文本;支持\n\x" size="small"
|
||||
style="width: 100px">
|
||||
<template #prepend>
|
||||
<el-button size="small" @click="store.frameBreakAfterSequence = false">
|
||||
|
|
|
@ -12,27 +12,37 @@
|
|||
</template>
|
||||
<el-button type="info" @click="resetSettings">重置</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
effect="light"
|
||||
placement="top"
|
||||
>
|
||||
<template #content>
|
||||
<p>若存在多个页面,会相互覆盖</p>
|
||||
</template>
|
||||
<el-checkbox border v-model="store.autoSaveSettings">保存至本地</el-checkbox>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center mb-2 flex-wrap gap-2">
|
||||
<el-button type="primary" @click="() => {
|
||||
macroData.push({
|
||||
store.macroData.push({
|
||||
value: '',
|
||||
label: '发送',
|
||||
id: macroId,
|
||||
id: store.macroId,
|
||||
})
|
||||
macroId++;
|
||||
store.macroId++;
|
||||
}">添加
|
||||
</el-button>
|
||||
<el-checkbox v-model="editMode" border>编辑</el-checkbox>
|
||||
<el-checkbox v-model="draggableEnabled" border>拖拽</el-checkbox>
|
||||
</div>
|
||||
<div>
|
||||
<el-alert v-if="store.ipChangeAlert" @close="store.ipChangeAlert=false">IP地址改变会导致配置丢失</el-alert>
|
||||
</div>
|
||||
|
||||
<el-alert>IP地址改变会导致配置丢失</el-alert>
|
||||
|
||||
<VueDraggable v-model="macroData" handle=".sort-target"
|
||||
<VueDraggable v-model="store.macroData" handle=".sort-target"
|
||||
:animation="150" class="break-input">
|
||||
<div v-for="(item, index) in macroData" :key="item.id" class="w-full text-xs flex items-center py-0.5"
|
||||
<div v-for="(item, index) in store.macroData" :key="item.id" class="w-full text-xs flex items-center py-0.5"
|
||||
:class="editMode ? 'macroButtons' : ''">
|
||||
<el-tag size="large" type="success" v-if="draggableEnabled" class="sort-target mr-1">
|
||||
=
|
||||
|
@ -43,7 +53,7 @@
|
|||
<el-button v-else @click="onSendClick(item.value)" type="primary">{{ item.label }}</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
<el-link :underline="false" @click="macroData.splice(index, 1);">
|
||||
<el-link :underline="false" @click="store.macroData.splice(index, 1);">
|
||||
<el-tag size="large" type="danger" v-if="editMode" class="ml-1">
|
||||
x
|
||||
</el-tag>
|
||||
|
@ -54,65 +64,15 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import {VueDraggable} from "vue-draggable-plus";
|
||||
import {type Ref, ref} from "vue";
|
||||
import {onMounted, ref} from "vue";
|
||||
import {globalNotify, globalNotifyRightSide} from "@/composables/notification";
|
||||
import {useDataViewerStore} from "@/stores/dataViewerStore";
|
||||
import {useStorage} from '@vueuse/core';
|
||||
|
||||
const editMode = ref(false);
|
||||
const draggableEnabled = ref(true);
|
||||
const store = useDataViewerStore();
|
||||
const emit = defineEmits(['winSizeRefresh'])
|
||||
|
||||
interface macroItem {
|
||||
value: string;
|
||||
label: string;
|
||||
id: number;
|
||||
}
|
||||
|
||||
const macroDataDefault: Ref<macroItem[]> = ref([
|
||||
{
|
||||
value: 'AT',
|
||||
label: '测试AT',
|
||||
id: 1,
|
||||
},{
|
||||
value: 'AT+CSQ',
|
||||
label: '询信号强度',
|
||||
id: 2,
|
||||
},{
|
||||
value: 'AT+CGSN',
|
||||
label: '询序列号',
|
||||
id: 3,
|
||||
}, {
|
||||
value: 'AT+CGMR',
|
||||
label: '询固件版本',
|
||||
id: 4,
|
||||
}, {
|
||||
value: 'AT+CMEE',
|
||||
label: '询终端报错',
|
||||
id: 5,
|
||||
}, {
|
||||
value: 'AT+NRB',
|
||||
label: '重启',
|
||||
id: 6,
|
||||
}, {
|
||||
value: 'AT+CGATT',
|
||||
label: '询网络激活状态',
|
||||
id: 7,
|
||||
}, {
|
||||
value: 'AT+CEREG',
|
||||
label: '询网络注册状态',
|
||||
id: 8,
|
||||
}, {
|
||||
value: 'AT+CSCON',
|
||||
label: '询网络连接状态',
|
||||
id: 9,
|
||||
}
|
||||
]);
|
||||
|
||||
const macroData = useStorage('macroItems', macroDataDefault);
|
||||
let macroId = macroData.value.reduce((max, item) => Math.max(max, item.id), 0) + 1;
|
||||
|
||||
function onSendClick(val: string) {
|
||||
if (!val && !store.hasAddedText) {
|
||||
globalNotify("无帧头帧尾、发送框无数据发送")
|
||||
|
@ -126,41 +86,6 @@ function onSendClick(val: string) {
|
|||
}
|
||||
}
|
||||
|
||||
interface DataViewerState {
|
||||
macroButtons: any; // Specify more precise types
|
||||
configTab: string;
|
||||
showText: boolean;
|
||||
showHex: boolean;
|
||||
showHexdump: boolean;
|
||||
showTimestamp: boolean;
|
||||
lineWrap: boolean;
|
||||
RxHexdumpColor: string;
|
||||
TxHexdumpColor: string;
|
||||
frameBreakSequence: string;
|
||||
frameBreakAfterSequence: boolean;
|
||||
frameBreakDelay: number;
|
||||
frameBreakSize: number;
|
||||
frameBreak: any[]; // Specify more precise types
|
||||
decodeANSI: boolean;
|
||||
frameFilterValue: string;
|
||||
autoUpdate: boolean;
|
||||
updateInterval: number;
|
||||
sendFramePrefix: string;
|
||||
sendFrameSuffix: string;
|
||||
loopSendInterval: number;
|
||||
sendBoxIsText: boolean;
|
||||
sendBox: string;
|
||||
winLeft: any;
|
||||
winRight: any;
|
||||
winAutoLayout: boolean;
|
||||
winLayoutMode: string;
|
||||
}
|
||||
|
||||
|
||||
function isKeyOfDataViewerState(key: any): key is keyof DataViewerState {
|
||||
return key in useDataViewerStore().$state;
|
||||
}
|
||||
|
||||
function importSettings() {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
|
@ -177,96 +102,7 @@ function importSettings() {
|
|||
if (typeof text !== 'string') return;
|
||||
|
||||
try {
|
||||
const data = JSON.parse(text) as Partial<DataViewerState>;
|
||||
|
||||
|
||||
if (data.macroButtons) {
|
||||
macroData.value = data.macroButtons;
|
||||
}
|
||||
if (data.configTab) {
|
||||
viewerStore.configPanelTab = data.configTab;
|
||||
}
|
||||
if (data.showText) {
|
||||
viewerStore.showText = data.showText;
|
||||
}
|
||||
if (data.showHex) {
|
||||
viewerStore.showHex = data.showHex;
|
||||
}
|
||||
if (data.showHexdump) {
|
||||
viewerStore.showHexdump = data.showHexdump;
|
||||
}
|
||||
if (data.showTimestamp) {
|
||||
viewerStore.showTimestamp = data.showTimestamp;
|
||||
}
|
||||
if (data.lineWrap) {
|
||||
viewerStore.enableLineWrap = data.lineWrap;
|
||||
}
|
||||
if (data.RxHexdumpColor) {
|
||||
viewerStore.RxHexdumpColor = data.RxHexdumpColor;
|
||||
}
|
||||
if (data.TxHexdumpColor) {
|
||||
viewerStore.TxHexdumpColor = data.TxHexdumpColor;
|
||||
}
|
||||
if (data.frameBreakSequence) {
|
||||
viewerStore.frameBreakSequence = data.frameBreakSequence;
|
||||
}
|
||||
if (data.frameBreakAfterSequence) {
|
||||
viewerStore.frameBreakAfterSequence = data.frameBreakAfterSequence;
|
||||
}
|
||||
if (data.frameBreakDelay) {
|
||||
viewerStore.frameBreakDelay = data.frameBreakDelay;
|
||||
}
|
||||
if (data.frameBreakSize) {
|
||||
viewerStore.frameBreakSize = data.frameBreakSize;
|
||||
}
|
||||
|
||||
if (data.frameBreak) {
|
||||
viewerStore.frameBreakRules = data.frameBreak;
|
||||
}
|
||||
if (data.decodeANSI) {
|
||||
viewerStore.enableAnsiDecode = data.decodeANSI;
|
||||
}
|
||||
if (data.frameFilterValue) {
|
||||
viewerStore.filterValue = data.frameFilterValue;
|
||||
}
|
||||
if (data.autoUpdate) {
|
||||
viewerStore.dataFilterAutoUpdate = data.autoUpdate;
|
||||
}
|
||||
if (data.updateInterval) {
|
||||
viewerStore.batchUpdateTime = data.updateInterval;
|
||||
}
|
||||
|
||||
if (data.sendFramePrefix) {
|
||||
viewerStore.textPrefixValue = data.sendFramePrefix;
|
||||
}
|
||||
if (data.sendFrameSuffix) {
|
||||
viewerStore.textSuffixValue = data.sendFrameSuffix;
|
||||
}
|
||||
|
||||
if (data.loopSendInterval) {
|
||||
viewerStore.loopSendFreq = data.loopSendInterval;
|
||||
}
|
||||
if (data.sendBoxIsText) {
|
||||
viewerStore.isSendTextFormat = data.sendBoxIsText;
|
||||
}
|
||||
if (data.sendBox) {
|
||||
viewerStore.uartInputTextBox = data.sendBox;
|
||||
}
|
||||
|
||||
if (data.winLeft) {
|
||||
viewerStore.winLeft = data.winLeft;
|
||||
}
|
||||
if (data.winRight) {
|
||||
viewerStore.winRight = data.winRight;
|
||||
}
|
||||
if (data.winAutoLayout !== undefined) {
|
||||
viewerStore.winAutoLayout = data.winAutoLayout;
|
||||
}
|
||||
if (data.winLayoutMode) {
|
||||
viewerStore.winLayoutMode = data.winLayoutMode;
|
||||
}
|
||||
|
||||
viewerStore.reloadFrameBreak();
|
||||
store.loadSettings(text);
|
||||
emit('winSizeRefresh', '');
|
||||
} catch (error) {
|
||||
globalNotifyRightSide('导入失败', "error");
|
||||
|
@ -280,48 +116,12 @@ function importSettings() {
|
|||
input.click();
|
||||
}
|
||||
|
||||
const viewerStore = useDataViewerStore();
|
||||
|
||||
function exportSettings() {
|
||||
let obj = {
|
||||
version: "v0.1.0",
|
||||
|
||||
/* Macro Window */
|
||||
macroButtons: macroData.value,
|
||||
|
||||
/* Config Window */
|
||||
configTab: viewerStore.configPanelTab,
|
||||
showText: viewerStore.showText,
|
||||
showHex: viewerStore.showHex,
|
||||
showHexdump: viewerStore.showHexdump,
|
||||
showTimestamp: viewerStore.showTimestamp,
|
||||
lineWrap: viewerStore.enableLineWrap,
|
||||
RxHexdumpColor: viewerStore.RxHexdumpColor,
|
||||
TxHexdumpColor: viewerStore.TxHexdumpColor,
|
||||
frameBreak: viewerStore.frameBreakRules,
|
||||
frameBreakSequence: viewerStore.frameBreakSequence,
|
||||
frameBreakAfterSequence: viewerStore.frameBreakAfterSequence,
|
||||
frameBreakDelay: viewerStore.frameBreakDelay,
|
||||
frameBreakSize: viewerStore.frameBreakSize,
|
||||
|
||||
decodeANSI: viewerStore.enableAnsiDecode,
|
||||
frameFilterValue: viewerStore.filterValue,
|
||||
autoUpdate: viewerStore.dataFilterAutoUpdate,
|
||||
updateInterval: viewerStore.batchUpdateTime,
|
||||
|
||||
sendFramePrefix: viewerStore.textPrefixValue,
|
||||
sendFrameSuffix: viewerStore.textSuffixValue,
|
||||
|
||||
/* Viewer Window */
|
||||
loopSendInterval: viewerStore.loopSendFreq,
|
||||
sendBoxIsText: viewerStore.isSendTextFormat,
|
||||
sendBox: viewerStore.uartInputTextBox,
|
||||
|
||||
/* layout settings */
|
||||
winLeft: viewerStore.winLeft,
|
||||
winRight: viewerStore.winRight,
|
||||
winAutoLayout: viewerStore.winAutoLayout,
|
||||
winLayoutMode: viewerStore.winLayoutMode,
|
||||
...store.settings
|
||||
};
|
||||
|
||||
const dataStr = JSON.stringify(obj, null, 2);
|
||||
|
@ -340,6 +140,10 @@ function resetSettings() {
|
|||
localStorage.clear();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
store.loadSettings();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
transition="none"
|
||||
width="300"
|
||||
>
|
||||
<div v-if="!store.configPanelShow" class="h-[40vh] overflow-auto">
|
||||
<div v-if="!store.winLeft.show" class="h-[40vh] overflow-auto">
|
||||
<text-data-config></text-data-config>
|
||||
</div>
|
||||
<template #reference>
|
||||
<el-link v-show="!store.configPanelShow" type="primary">
|
||||
<el-link v-show="!store.winLeft.show" type="primary">
|
||||
<InlineSvg name="arrow_drop_down" class="h-6 mb-1 px-2"></InlineSvg>
|
||||
</el-link>
|
||||
</template>
|
||||
|
|
Loading…
Reference in New Issue