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:
kerms 2024-08-02 21:38:13 +08:00
parent 8e0d8234e5
commit dd1b9adc0d
5 changed files with 313 additions and 278 deletions

View File

@ -8,7 +8,7 @@ import {
watch, watch,
} from "vue"; } from "vue";
import {AnsiUp} from 'ansi_up' 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 {type IUartConfig, uart_send_msg} from "@/api/apiUart";
import {isDevMode} from "@/composables/buildMode"; import {isDevMode} from "@/composables/buildMode";
import {useUartStore} from "@/stores/useUartStore"; 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', () => { export const useDataViewerStore = defineStore('text-viewer', () => {
const uartStore = useUartStore() const uartStore = useUartStore()
@ -270,10 +308,8 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
generateBaudArr(uartBaudList); generateBaudArr(uartBaudList);
/* public value */ /* public value */
const configPanelTab = useStorage("configTab" ,"second"); const configPanelTab = ref("second");
const configPanelShow = ref(true); const enableAnsiDecode = ref(true);
const quickAccessPanelShow = ref(true);
const enableAnsiDecode = useStorage("decodeANSI", true);
/* /*
@ -283,12 +319,12 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
let RxSegment: Uint8Array = new Uint8Array(0); let RxSegment: Uint8Array = new Uint8Array(0);
const RxRemainHexdump = ref(""); const RxRemainHexdump = ref("");
const frameBreakSequence = useStorage("frameBreakSequence", "\\n"); const frameBreakSequence = ref("\\n");
const frameBreakAfterSequence = useStorage("frameBreakAfterSequence", true); const frameBreakAfterSequence = ref(true);
const frameBreakSequenceNormalized = computed(() => { const frameBreakSequenceNormalized = computed(() => {
return unescapeString(frameBreakSequence.value); return unescapeString(frameBreakSequence.value);
}); });
const frameBreakDelay = useStorage("frameBreakDelay", 0); const frameBreakDelay = ref(0);
let frameBreakDelayTimeoutID: number = -1; let frameBreakDelayTimeoutID: number = -1;
function frameBreakFlush() { function frameBreakFlush() {
@ -326,27 +362,24 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
const frameBreakSize = useStorage("frameBreakSize", 0); const frameBreakSize = ref(0);
const frameBreakRules = useStorage("breakRules", [{ const frameBreakRules = ref([{
ref: frameBreakDelay,
name: '超时(ms)', name: '超时(ms)',
type: 'number', type: 'number',
min: -1, min: -1,
draggable: false, draggable: false,
transformData: breakDelay, transformData: breakDelay,
}, { }, {
ref: frameBreakSequence,
name: '匹配', name: '匹配',
type: 'text', type: 'text',
draggable: true, draggable: true,
transformData: breakDelay, transformData: breakSequence,
}, { }, {
ref: frameBreakSize,
name: '字节(B)', name: '字节(B)',
type: 'number', type: 'number',
min: 0, min: 0,
draggable: true, draggable: true,
transformData: breakDelay, transformData: breakSize,
},]) },])
function breakDelay(inputArray: Uint8Array[]) { function breakDelay(inputArray: Uint8Array[]) {
@ -406,19 +439,14 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
for (let i = 0; i < frameBreakRules.value.length; i++) { for (let i = 0; i < frameBreakRules.value.length; i++) {
if (frameBreakRules.value[i].name === "超时(ms)") { if (frameBreakRules.value[i].name === "超时(ms)") {
frameBreakRules.value[i].transformData = breakDelay; frameBreakRules.value[i].transformData = breakDelay;
frameBreakRules.value[i].ref = frameBreakDelay;
} else if (frameBreakRules.value[i].name === "匹配") { } else if (frameBreakRules.value[i].name === "匹配") {
frameBreakRules.value[i].transformData = breakSequence; frameBreakRules.value[i].transformData = breakSequence;
frameBreakRules.value[i].ref = frameBreakSequence;
} else { } else {
frameBreakRules.value[i].transformData = breakSize; frameBreakRules.value[i].transformData = breakSize;
frameBreakRules.value[i].ref = frameBreakSize;
} }
} }
} }
reloadFrameBreak();
function addStringMessage(input: string, isRX: boolean, doSend: boolean = false) { function addStringMessage(input: string, isRX: boolean, doSend: boolean = false) {
const unescaped = unescapeString(input); const unescaped = unescapeString(input);
addSegment(unescaped, isRX, doSend); addSegment(unescaped, isRX, doSend);
@ -478,21 +506,20 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
RxRemainHexdump, RxRemainHexdump,
addStringMessage, addStringMessage,
addSegment, addSegment,
reloadFrameBreak,
} }
const showText = useStorage('showText', true); const showText = ref(true);
const showHex = useStorage('showHex', false); const showHex = ref(false);
const showHexdump = useStorage('showHexdump', false); const showHexdump = ref(false);
const enableLineWrap = useStorage('lineWrap', false); const enableLineWrap = ref(false);
const showTimestamp = useStorage('showTimestamp', true); const showTimestamp = ref(true);
const showVirtualScroll = ref(true); const showVirtualScroll = ref(true);
const RxHexdumpColor = useStorage('RxHexdumpColor', "#f0f9eb"); const RxHexdumpColor = ref("#f0f9eb");
const RxTotalByteCount = ref(0); const RxTotalByteCount = ref(0);
const RxByteCount = ref(0); const RxByteCount = ref(0);
const TxHexdumpColor = useStorage('TxHexdumpColor', "#ecf4ff"); const TxHexdumpColor = ref("#ecf4ff");
const TxTotalByteCount = ref(0); const TxTotalByteCount = ref(0);
const TxByteCount = ref(0); const TxByteCount = ref(0);
@ -515,8 +542,8 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
const forceToBottom = ref(true); const forceToBottom = ref(true);
const filterChanged = ref(false); const filterChanged = ref(false);
const textPrefixValue = useStorage('sendFramePrefix', ""); const textPrefixValue = ref("");
const textSuffixValue = useStorage('sendFrameSuffix', "\\r\\n"); const textSuffixValue = ref("\\r\\n");
const hasAddedText = computed(() => { const hasAddedText = computed(() => {
return textPrefixValue.value.length > 0 || textSuffixValue.value.length > 0; return textPrefixValue.value.length > 0 || textSuffixValue.value.length > 0;
}); });
@ -529,7 +556,7 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
stop_bits: 1, stop_bits: 1,
}); });
const filterValue = useStorage('frameFilterValue', ''); const filterValue = ref('');
const computedFilterValue = computed(() => { const computedFilterValue = computed(() => {
return unescapeString(filterValue.value); return unescapeString(filterValue.value);
}) })
@ -547,7 +574,7 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
/* actual data shown on screen */ /* actual data shown on screen */
const dataFiltered: ShallowReactive<IDataBuf[]> = shallowReactive([]); const dataFiltered: ShallowReactive<IDataBuf[]> = shallowReactive([]);
const dataFilterAutoUpdate = useStorage("autoUpdate", true); const dataFilterAutoUpdate = ref(true);
const acceptIncomingData = ref(false); const acceptIncomingData = ref(false);
// let frameBreakReady = false; // let frameBreakReady = false;
@ -559,7 +586,7 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
}, {debounce: 300}); }, {debounce: 300});
let batchDataUpdateIntervalID: number = -1; let batchDataUpdateIntervalID: number = -1;
const batchUpdateTime = useStorage('updateInterval', 80); /* ms */ const batchUpdateTime = ref(80); /* ms */
let batchStartIndex: number = 0; let batchStartIndex: number = 0;
watch(batchUpdateTime, () => { watch(batchUpdateTime, () => {
@ -780,10 +807,10 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
const enableLoopSend = ref(false); const enableLoopSend = ref(false);
const loopSendFreq = useStorage('loopSendInterval', 1000); const loopSendFreq = ref(1000);
let loopSendIntervalID: number = -1; let loopSendIntervalID: number = -1;
const uartInputTextBox = useStorage('sendBox', ""); const sendBox = ref("");
const isSendTextFormat = useStorage('sendBoxIsText', true); const sendBoxIsText = ref(true);
const isHexStringValid = ref(false); const isHexStringValid = ref(false);
function loopSend() { function loopSend() {
@ -791,14 +818,14 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
enableLoopSend.value = false; enableLoopSend.value = false;
} }
if (isSendTextFormat.value) { if (sendBoxIsText.value) {
addString(uartInputTextBox.value, false, true); addString(sendBox.value, false, true);
} else { } else {
if (!isHexStringValid.value) { if (!isHexStringValid.value) {
addString("HEX格式错误", false, false, 1); addString("HEX格式错误", false, false, 1);
addHexString(uartInputTextBox.value, false, false, 1); addHexString(sendBox.value, false, false, 1);
} else { } else {
addHexString(uartInputTextBox.value, false, true); addHexString(sendBox.value, false, true);
} }
} }
} }
@ -829,8 +856,8 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
enableLoopSend, enableLoopSend,
loopSendFreq, loopSendFreq,
loopSendIntervalID, loopSendIntervalID,
isSendTextFormat, isSendTextFormat: sendBoxIsText,
uartInputTextBox, uartInputTextBox: sendBox,
isHexStringValid, isHexStringValid,
} }
@ -842,7 +869,7 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
} }
/* window layout */ /* window layout */
const winLeft = useStorage('winLeft',{ const winLeft = ref({
show: true, show: true,
width: "100px", width: "100px",
height: "100px", height: "100px",
@ -850,15 +877,15 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
}); });
/* window layout */ /* window layout */
const winRight = useStorage('winRight',{ const winRight = ref({
show: true, show: true,
width: "100px", width: "100px",
height: "100px", height: "100px",
borderSize: 3, borderSize: 3,
}); });
const winAutoLayout = useStorage('winAuto', true); const winAutoLayout = ref(true);
const winLayoutMode = useStorage('winLayout', 'row'); const winLayoutMode = ref('row');
const winLayoutRet = { const winLayoutRet = {
@ -868,6 +895,204 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
winLayoutMode, 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 { return {
addItem, addItem,
addString, addString,
@ -882,8 +1107,6 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
clearByteCount, clearByteCount,
dataBufLength, dataBufLength,
configPanelTab, configPanelTab,
configPanelShow,
quickAccessPanelShow,
dataFiltered, dataFiltered,
dataFilterAutoUpdate, dataFilterAutoUpdate,
filterValue, filterValue,
@ -921,5 +1144,12 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
setUartBaud, setUartBaud,
...loopSendRet, ...loopSendRet,
...winLayoutRet, ...winLayoutRet,
...macroDataRet,
autoSaveSettings,
settings,
testNumber,
loadSettings,
ipChangeAlert,
} }
}); });

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="button-m-0 messages-container flex flex-grow overflow-hidden" :class="{'flex-col': store.winLayoutMode ==='col'}"> <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="{ :class="{
'max-w-60': store.winLayoutMode==='row', 'xl:max-w-80': store.winLayoutMode==='row', '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' 'min-w-60': store.winLayoutMode==='row', 'xl:min-w-80': store.winLayoutMode==='row'
@ -9,7 +9,7 @@
<text-data-config></text-data-config> <text-data-config></text-data-config>
</div> </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"> <div v-show="winDataView.show" class="flex flex-col flex-grow overflow-hidden p-2">
<textDataViewer></textDataViewer> <textDataViewer></textDataViewer>
@ -40,7 +40,7 @@
</div> </div>
<el-checkbox label="自适应" v-model="store.winAutoLayout" border size="small" <el-checkbox label="自适应" v-model="store.winAutoLayout" border size="small"
:disabled="store.winLayoutMode==='col'"/> :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="winDataView.show" border size="small" :disabled="store.winAutoLayout"/>
<el-checkbox label="快捷窗" v-model="store.winRight.show" border size="small" :disabled="store.winAutoLayout"/> <el-checkbox label="快捷窗" v-model="store.winRight.show" border size="small" :disabled="store.winAutoLayout"/>
</div> </div>
@ -298,7 +298,7 @@ watch([
() => store.winAutoLayout () => store.winAutoLayout
], (value) => { ], (value) => {
if (store.winAutoLayout) { if (store.winAutoLayout) {
store.configPanelShow = !value[0]; store.winLeft.show = !value[0];
win1Ref.value.style.minWidth = ""; win1Ref.value.style.minWidth = "";
win1Ref.value.style.maxWidth = ""; win1Ref.value.style.maxWidth = "";
win2Ref.value.style.minWidth = ""; win2Ref.value.style.minWidth = "";

View File

@ -4,7 +4,7 @@
<el-tab-pane label="接口" name="first" class="min-h-80"> <el-tab-pane label="接口" name="first" class="min-h-80">
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<el-form :size="store.configPanelShow ? '' : 'small'"> <el-form :size="store.winLeft.show ? '' : 'small'">
<el-form-item <el-form-item
label="波特率" label="波特率"
class="mb-2" class="mb-2"
@ -179,10 +179,11 @@
<td :class="item.draggable ? 'sort-target' : ''">{{ item.name }}</td> <td :class="item.draggable ? 'sort-target' : ''">{{ item.name }}</td>
<td> <td>
<div v-if="item.type === 'number'"> <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>
<div v-else> <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"> style="width: 100px">
<template #prepend> <template #prepend>
<el-button size="small" @click="store.frameBreakAfterSequence = false"> <el-button size="small" @click="store.frameBreakAfterSequence = false">

View File

@ -12,27 +12,37 @@
</template> </template>
<el-button type="info" @click="resetSettings">重置</el-button> <el-button type="info" @click="resetSettings">重置</el-button>
</el-tooltip> </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>
<div class="flex items-center mb-2 flex-wrap gap-2"> <div class="flex items-center mb-2 flex-wrap gap-2">
<el-button type="primary" @click="() => { <el-button type="primary" @click="() => {
macroData.push({ store.macroData.push({
value: '', value: '',
label: '发送', label: '发送',
id: macroId, id: store.macroId,
}) })
macroId++; store.macroId++;
}">添加 }">添加
</el-button> </el-button>
<el-checkbox v-model="editMode" border>编辑</el-checkbox> <el-checkbox v-model="editMode" border>编辑</el-checkbox>
<el-checkbox v-model="draggableEnabled" border>拖拽</el-checkbox> <el-checkbox v-model="draggableEnabled" border>拖拽</el-checkbox>
</div> </div>
<div>
<el-alert v-if="store.ipChangeAlert" @close="store.ipChangeAlert=false">IP地址改变会导致配置丢失</el-alert>
</div>
<el-alert>IP地址改变会导致配置丢失</el-alert> <VueDraggable v-model="store.macroData" handle=".sort-target"
<VueDraggable v-model="macroData" handle=".sort-target"
:animation="150" class="break-input"> :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' : ''"> :class="editMode ? 'macroButtons' : ''">
<el-tag size="large" type="success" v-if="draggableEnabled" class="sort-target mr-1"> <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> <el-button v-else @click="onSendClick(item.value)" type="primary">{{ item.label }}</el-button>
</template> </template>
</el-input> </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"> <el-tag size="large" type="danger" v-if="editMode" class="ml-1">
x x
</el-tag> </el-tag>
@ -54,65 +64,15 @@
<script setup lang="ts"> <script setup lang="ts">
import {VueDraggable} from "vue-draggable-plus"; import {VueDraggable} from "vue-draggable-plus";
import {type Ref, ref} from "vue"; import {onMounted, ref} from "vue";
import {globalNotify, globalNotifyRightSide} from "@/composables/notification"; import {globalNotify, globalNotifyRightSide} from "@/composables/notification";
import {useDataViewerStore} from "@/stores/dataViewerStore"; import {useDataViewerStore} from "@/stores/dataViewerStore";
import {useStorage} from '@vueuse/core';
const editMode = ref(false); const editMode = ref(false);
const draggableEnabled = ref(true); const draggableEnabled = ref(true);
const store = useDataViewerStore(); const store = useDataViewerStore();
const emit = defineEmits(['winSizeRefresh']) 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) { function onSendClick(val: string) {
if (!val && !store.hasAddedText) { if (!val && !store.hasAddedText) {
globalNotify("无帧头帧尾、发送框无数据发送") 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() { function importSettings() {
const input = document.createElement('input'); const input = document.createElement('input');
input.type = 'file'; input.type = 'file';
@ -177,96 +102,7 @@ function importSettings() {
if (typeof text !== 'string') return; if (typeof text !== 'string') return;
try { try {
const data = JSON.parse(text) as Partial<DataViewerState>; store.loadSettings(text);
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();
emit('winSizeRefresh', ''); emit('winSizeRefresh', '');
} catch (error) { } catch (error) {
globalNotifyRightSide('导入失败', "error"); globalNotifyRightSide('导入失败', "error");
@ -280,48 +116,12 @@ function importSettings() {
input.click(); input.click();
} }
const viewerStore = useDataViewerStore();
function exportSettings() { function exportSettings() {
let obj = { let obj = {
version: "v0.1.0", version: "v0.1.0",
/* Macro Window */ /* Macro Window */
macroButtons: macroData.value, ...store.settings
/* 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,
}; };
const dataStr = JSON.stringify(obj, null, 2); const dataStr = JSON.stringify(obj, null, 2);
@ -340,6 +140,10 @@ function resetSettings() {
localStorage.clear(); localStorage.clear();
} }
onMounted(() => {
store.loadSettings();
});
</script> </script>

View File

@ -7,11 +7,11 @@
transition="none" transition="none"
width="300" 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> <text-data-config></text-data-config>
</div> </div>
<template #reference> <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> <InlineSvg name="arrow_drop_down" class="h-6 mb-1 px-2"></InlineSvg>
</el-link> </el-link>
</template> </template>