feat: 添加跨度菜单列表及其项目,更新频谱仪状态管理
All checks were successful
/ build-and-deploy-to-vercel (push) Successful in 2m57s
/ surge (push) Successful in 2m42s
/ cleanup_surge (push) Successful in 16s
/ playwright (push) Successful in 55s
/ lint-build-and-check (push) Successful in 6m13s

This commit is contained in:
严浩
2025-05-08 18:10:27 +08:00
parent 243b2bbd6b
commit b850ae82ae
2 changed files with 185 additions and 57 deletions

View File

@ -1,6 +1,13 @@
export enum E_选项卡菜单 {
= '频率单位列表',
= '频率菜单列表',
= '跨度菜单列表',
}
export enum E_跨度菜单列表的项目 {
FullSpan = 'Full Span',
ZeroSpan = 'Zero Span',
LastSpan = 'Last Span',
}
/* 值是在屏幕上显示的值。 */

View File

@ -2,13 +2,19 @@
<script setup lang="ts">
import { $enum } from 'ts-enum-util';
import { E_Freq单位, E_数字键盘按键, E_选项卡菜单, E_选项卡菜单Freq菜单列表的项目 } from './CONST';
import {
E_Freq单位,
E_数字键盘按键,
E_跨度菜单列表的项目,
E_选项卡菜单,
E_选项卡菜单Freq菜单列表的项目,
} from './CONST';
import 设备照片 from './pin-pu-yi-bg.png';
const state = reactive({
选项卡当前显示: E_选项卡菜单.频率菜单列表,
状态: {
输入状态: {
谱仪状态: {
频率输入状态: {
选中的频率菜单列表的项目: null as E_选项卡菜单Freq菜单列表的项目 | null,
输入的值临时输入字符串: null as null | string, // 用于暂存用户输入
},
@ -24,6 +30,24 @@ const state = reactive({
value: 0,
unit: E_Freq单位.Hz,
},
span: {
currentSpan: {
start: 0,
stop: 0,
unit: E_Freq单位.Hz,
},
lastSpan: {
start: 0,
stop: 0,
unit: E_Freq单位.Hz,
},
fullSpan: {
start: 0,
stop: 3,
unit: E_Freq单位.GHz,
},
zeroSpan: false,
},
},
});
@ -31,6 +55,7 @@ const 选项卡标题 = computed(() =>
$enum.mapValue(state.选项卡当前显示).with({
[E_选项卡菜单.频率菜单列表]: 'Freq/Channel',
[E_选项卡菜单.频率单位列表]: '',
[E_选项卡菜单.跨度菜单列表]: 'Span',
}),
);
@ -39,17 +64,17 @@ function 执行点击屏幕右边的按钮(按钮序号: number) {
if (state.选项卡当前显示 === E_选项卡菜单.频率菜单列表) {
switch (按钮序号) {
case 1: {
state.状态.输入状态.选中的频率菜单列表的项目 = E_选项卡菜单Freq菜单列表的项目.CenterFreq;
state.谱仪状态.频率输入状态.选中的频率菜单列表的项目 = E_选项卡菜单Freq菜单列表的项目.CenterFreq;
console.debug('设置 Freq 输入状态为 CenterFreq');
break;
}
case 2: {
state.状态.输入状态.选中的频率菜单列表的项目 = E_选项卡菜单Freq菜单列表的项目.StartFreq;
state.谱仪状态.频率输入状态.选中的频率菜单列表的项目 = E_选项卡菜单Freq菜单列表的项目.StartFreq;
console.debug('设置 Freq 输入状态为 StartFreq');
break;
}
case 3: {
state.状态.输入状态.选中的频率菜单列表的项目 = E_选项卡菜单Freq菜单列表的项目.StopFreq;
state.谱仪状态.频率输入状态.选中的频率菜单列表的项目 = E_选项卡菜单Freq菜单列表的项目.StopFreq;
console.debug('设置 Freq 输入状态为 StopFreq');
break;
}
@ -86,8 +111,8 @@ function 执行点击屏幕右边的按钮(按钮序号: number) {
} // 不处理无效按钮 (5, 6, 7)
}
const tempInputString = state.状态.输入状态.输入的值临时输入字符串;
const selectedFreqItem = state.状态.输入状态.选中的频率菜单列表的项目;
const tempInputString = state.谱仪状态.频率输入状态.输入的值临时输入字符串;
const selectedFreqItem = state.谱仪状态.频率输入状态.选中的频率菜单列表的项目;
// 必须有临时输入值和选中的 Freq 项目才能确认
if (!tempInputString || !selectedFreqItem) {
@ -114,34 +139,82 @@ function 执行点击屏幕右边的按钮(按钮序号: number) {
// 根据选中的 Freq 项目更新对应的状态
switch (selectedFreqItem) {
case E_选项卡菜单Freq菜单列表的项目.CenterFreq: {
state.状态.center.value = inputValue;
state.状态.center.unit = selectedUnit;
console.debug('更新 CenterFreq:', state.状态.center);
state.谱仪状态.center.value = inputValue;
state.谱仪状态.center.unit = selectedUnit;
console.debug('更新 CenterFreq:', state.谱仪状态.center);
break;
}
case E_选项卡菜单Freq菜单列表的项目.StartFreq: {
state.状态.start.value = inputValue;
state.状态.start.unit = selectedUnit;
console.debug('更新 StartFreq:', state.状态.start);
state.谱仪状态.start.value = inputValue;
state.谱仪状态.start.unit = selectedUnit;
console.debug('更新 StartFreq:', state.谱仪状态.start);
break;
}
case E_选项卡菜单Freq菜单列表的项目.StopFreq: {
state.状态.stop.value = inputValue;
state.状态.stop.unit = selectedUnit;
console.debug('更新 StopFreq:', state.状态.stop);
state.谱仪状态.stop.value = inputValue;
state.谱仪状态.stop.unit = selectedUnit;
console.debug('更新 StopFreq:', state.谱仪状态.stop);
break;
}
}
// 重置整个输入状态,为下一次输入做准备
state.状态.输入状态.选中的频率菜单列表的项目 = null;
state.状态.输入状态.输入的值临时输入字符串 = null;
state.谱仪状态.频率输入状态.选中的频率菜单列表的项目 = null;
state.谱仪状态.频率输入状态.输入的值临时输入字符串 = null;
console.debug('输入状态已重置');
// 操作完成,切换回 Freq 菜单列表
state.选项卡当前显示 = E_选项卡菜单.频率菜单列表;
console.debug('切换回 Freq 菜单列表');
}
if (state.选项卡当前显示 === E_选项卡菜单.跨度菜单列表) {
switch (按钮序号) {
case 1: {
// Full Span
state.频谱仪状态.span.lastSpan.start = state.频谱仪状态.start.value;
state.频谱仪状态.span.lastSpan.stop = state.频谱仪状态.stop.value;
state.频谱仪状态.span.lastSpan.unit = state.频谱仪状态.stop.unit;
state.频谱仪状态.start.value = state.频谱仪状态.span.fullSpan.start;
state.频谱仪状态.start.unit = state.频谱仪状态.span.fullSpan.unit;
state.频谱仪状态.stop.value = state.频谱仪状态.span.fullSpan.stop;
state.频谱仪状态.stop.unit = state.频谱仪状态.span.fullSpan.unit;
state.频谱仪状态.center.value = (state.频谱仪状态.start.value + state.频谱仪状态.stop.value) / 2;
state.频谱仪状态.center.unit = state.频谱仪状态.span.fullSpan.unit;
state.频谱仪状态.span.zeroSpan = false;
console.debug('设置为 Full Span');
break;
}
case 2: {
// Zero Span
state.频谱仪状态.span.lastSpan.start = state.频谱仪状态.start.value;
state.频谱仪状态.span.lastSpan.stop = state.频谱仪状态.stop.value;
state.频谱仪状态.span.lastSpan.unit = state.频谱仪状态.stop.unit;
state.频谱仪状态.start.value = state.频谱仪状态.center.value;
state.频谱仪状态.start.unit = state.频谱仪状态.center.unit;
state.频谱仪状态.stop.value = state.频谱仪状态.center.value;
state.频谱仪状态.stop.unit = state.频谱仪状态.center.unit;
state.频谱仪状态.span.zeroSpan = true;
console.debug('设置为 Zero Span');
break;
}
case 3: {
// Last Span
state.频谱仪状态.start.value = state.频谱仪状态.span.lastSpan.start;
state.频谱仪状态.start.unit = state.频谱仪状态.span.lastSpan.unit;
state.频谱仪状态.stop.value = state.频谱仪状态.span.lastSpan.stop;
state.频谱仪状态.stop.unit = state.频谱仪状态.span.lastSpan.unit;
state.频谱仪状态.center.value = (state.频谱仪状态.start.value + state.频谱仪状态.stop.value) / 2;
state.频谱仪状态.center.unit = state.频谱仪状态.span.lastSpan.unit;
state.频谱仪状态.span.zeroSpan = false;
console.debug('恢复到 Last Span');
break;
}
default: {
console.debug('这个按键还没有实现');
break;
}
}
}
console.groupEnd();
}
@ -149,14 +222,14 @@ function 执行点击数字按钮(按钮值: E_数字键盘按键) {
console.group('🔢 点击数字按钮', { 按钮值 });
// 检查是否已选择 Freq 菜单项
if (!state.状态.输入状态.选中的频率菜单列表的项目) {
if (!state.谱仪状态.频率输入状态.选中的频率菜单列表的项目) {
console.warn('请先选择一个 Freq 菜单项 (Center, Start, Stop)');
console.groupEnd();
return;
}
// 使用 临时输入字符串,如果为 null 则视为空字符串
const 当前临时输入 = state.状态.输入状态.输入的值临时输入字符串 ?? '';
const 当前临时输入 = state.谱仪状态.频率输入状态.输入的值临时输入字符串 ?? '';
switch (按钮值) {
case E_数字键盘按键.Dot: {
@ -165,8 +238,8 @@ function 执行点击数字按钮(按钮值: E_数字键盘按键) {
console.debug('已存在小数点,忽略本次输入');
} else {
// 如果当前为空,则为 '0.',否则追加 '.'
state.状态.输入状态.输入的值临时输入字符串 = 当前临时输入 ? `${当前临时输入}.` : '0.';
console.debug('输入小数点,临时字符串:', state.状态.输入状态.输入的值临时输入字符串);
state.谱仪状态.频率输入状态.输入的值临时输入字符串 = 当前临时输入 ? `${当前临时输入}.` : '0.';
console.debug('输入小数点,临时字符串:', state.谱仪状态.频率输入状态.输入的值临时输入字符串);
}
break;
}
@ -184,31 +257,31 @@ function 执行点击数字按钮(按钮值: E_数字键盘按键) {
// 直接拼接数字到临时字符串
// 特殊处理:如果当前是 '0',则替换为新数字;如果是 '-0',则替换为 '-'+新数字
if (当前临时输入 === '0') {
state.状态.输入状态.输入的值临时输入字符串 = String(按钮值);
state.谱仪状态.频率输入状态.输入的值临时输入字符串 = String(按钮值);
} else if (当前临时输入 === '-0') {
state.状态.输入状态.输入的值临时输入字符串 = `-${String(按钮值)}`;
state.谱仪状态.频率输入状态.输入的值临时输入字符串 = `-${String(按钮值)}`;
} else {
state.状态.输入状态.输入的值临时输入字符串 = 当前临时输入 + String(按钮值);
state.谱仪状态.频率输入状态.输入的值临时输入字符串 = 当前临时输入 + String(按钮值);
}
console.debug('输入数字,临时字符串:', state.状态.输入状态.输入的值临时输入字符串);
console.debug('输入数字,临时字符串:', state.谱仪状态.频率输入状态.输入的值临时输入字符串);
break;
}
case E_数字键盘按键.PlusMinus: {
// +/- 逻辑操作临时字符串
if (当前临时输入.startsWith('-')) {
// 如果已经是负数,移除负号
state.状态.输入状态.输入的值临时输入字符串 = 当前临时输入.slice(1);
state.谱仪状态.频率输入状态.输入的值临时输入字符串 = 当前临时输入.slice(1);
} else if (当前临时输入 && 当前临时输入 !== '0' && 当前临时输入 !== '0.') {
// 如果是正数且不为0或0.,添加负号
state.状态.输入状态.输入的值临时输入字符串 = `-${当前临时输入}`;
state.谱仪状态.频率输入状态.输入的值临时输入字符串 = `-${当前临时输入}`;
} else if (当前临时输入 === '' || 当前临时输入 === '0' || 当前临时输入 === '0.') {
// 如果是空或0或0.,变成负号开头
state.状态.输入状态.输入的值临时输入字符串 = '-';
state.谱仪状态.频率输入状态.输入的值临时输入字符串 = '-';
} else {
// 其他情况(例如只有一个'-')不允许切换
console.debug('无法切换正负号');
}
console.debug('切换正负号,临时字符串:', state.状态.输入状态.输入的值临时输入字符串);
console.debug('切换正负号,临时字符串:', state.谱仪状态.频率输入状态.输入的值临时输入字符串);
break;
}
default: {
@ -226,19 +299,19 @@ const img_modules = import.meta.glob<{ default: string }>('./imgs/*.png', {
});
const 屏幕照片 = ref(img_modules['./imgs/屏幕_0.png']!.default);
watch(
() => state.状态.center.value,
() => state.谱仪状态.center.value,
() => {
屏幕照片.value = img_modules['./imgs/屏幕_1.png']!.default;
},
);
watch(
() => state.状态.start.value,
() => state.谱仪状态.start.value,
() => {
屏幕照片.value = img_modules['./imgs/屏幕_2.png']!.default;
},
);
watch(
() => state.状态.stop.value,
() => state.谱仪状态.stop.value,
() => {
屏幕照片.value = img_modules['./imgs/屏幕_3.png']!.default;
},
@ -249,9 +322,12 @@ watchEffect(() => {
</script>
<template>
<!-- <pre v-if="$__DEV__" class="fixed top-10 right-10 z-[9999] bg-white text-black p-[10px] text-[12px] overflow-auto">{{
{ 选项卡菜单7个: $enum(E_选项卡菜单).getValues(), ...state }
}}</pre> -->
<pre
v-if="$__DEV__"
class="fixed overflow-y-auto top-10 bottom-10 right-10 z-[9999] bg-white text-black p-[10px] text-[12px] overflow-auto"
>{{ { 选项卡菜单7个: $enum(E_选项卡菜单).getValues(), ...state } }}</pre
>
<div class="wrp relative">
<img :src="设备照片" alt="频谱仪设备" />
@ -266,7 +342,7 @@ watchEffect(() => {
class="lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-visible rounded-[2px] text-[12px]"
@click="执行点击屏幕右边的按钮(n)"
>
<button class="ppy-btn !h-full !w-full">{{ n }}.</button>
<button class="ppy-btn !h-full !w-full"></button>
</li>
</template>
</ul>
@ -274,32 +350,53 @@ watchEffect(() => {
<div class="absolute left-[195px] top-[140px] h-[350px] w-[430px] bg-black" data-box="屏幕">
<img :src="屏幕照片" alt="频谱仪屏幕" class="absolute left-0 top-0 !h-[330px] !w-[340px]" />
<!-- bg-pink -->
<div data-box="下面左Start 右Stop" class="absolute left-0 right-85px bottom-0 flex justify-between text-white">
<div class="flex-1 text-left text-center">
<span>Start </span>
<span>{{ state.频谱仪状态.start.value }}</span>
<span>{{ state.频谱仪状态.start.unit }}</span>
</div>
<div class="flex-1 text-right text-center">
<span>Stop </span>
<span>{{ state.频谱仪状态.stop.value }}</span>
<span>{{ state.频谱仪状态.stop.unit }}</span>
</div>
</div>
<div
v-if="state.频状态.输入状态.选中的频率菜单列表的项目"
v-if="state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目"
class="lh-[1.2] absolute left-[40px] top-[140px] flex flex-col gap-y-[0px] bg-gray-500/100 text-white"
data-box="显示输入的 Freq/Channel 的值"
data-box="正在输入频率"
>
<!-- 优先显示临时输入字符串如果为空则显示默认或已确认的值 -->
<div>{{ state.状态.输入状态.选中的频率菜单列表的项目 }}</div>
<div>{{ state.谱仪状态.频率输入状态.选中的频率菜单列表的项目 }}</div>
<div>
<template v-if="state.频状态.输入状态.输入的值临时输入字符串 !== null">
{{ state.频状态.输入状态.输入的值临时输入字符串 }}
<template v-if="state.频谱仪状态.频率输入状态.输入的值临时输入字符串 !== null">
{{ state.频谱仪状态.频率输入状态.输入的值临时输入字符串 }}
<!-- 输入过程中不显示单位等待单位确认 -->
</template>
<template
v-else-if="state.频率状态.输入状态.选中的频率菜单列表的项目 === E_选项卡菜单Freq菜单列表的项目.CenterFreq"
v-else-if="
state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目 === E_选项卡菜单Freq菜单列表的项目.CenterFreq
"
>
{{ state.频率状态.center.value }} {{ state.频率状态.center.unit }}
{{ state.频谱仪状态.center.value }} {{ state.频谱仪状态.center.unit }}
</template>
<template
v-else-if="state.频率状态.输入状态.选中的频率菜单列表的项目 === E_选项卡菜单Freq菜单列表的项目.StartFreq"
v-else-if="
state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目 === E_选项卡菜单Freq菜单列表的项目.StartFreq
"
>
{{ state.频率状态.start.value }} {{ state.频率状态.start.unit }}
{{ state.频谱仪状态.start.value }} {{ state.频谱仪状态.start.unit }}
</template>
<template
v-else-if="state.频率状态.输入状态.选中的频率菜单列表的项目 === E_选项卡菜单Freq菜单列表的项目.StopFreq"
v-else-if="
state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目 === E_选项卡菜单Freq菜单列表的项目.StopFreq
"
>
{{ state.频率状态.stop.value }} {{ state.频率状态.stop.unit }}
{{ state.频谱仪状态.stop.value }} {{ state.频谱仪状态.stop.unit }}
</template>
<template v-else>
<!-- 没有选中项目,也没有临时输入时显示默认 -->
@ -323,18 +420,18 @@ watchEffect(() => {
>
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
<span>Center Freq</span>
{{ state.频率状态.center.value }}
{{ state.频率状态.center.unit }}
{{ state.频谱仪状态.center.value }}
{{ state.频谱仪状态.center.unit }}
</li>
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
<span>Start Freq</span>
{{ state.频率状态.start.value }}
{{ state.频率状态.start.unit }}
{{ state.频谱仪状态.start.value }}
{{ state.频谱仪状态.start.unit }}
</li>
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
<span>Stop Freq</span>
{{ state.频率状态.stop.value }}
{{ state.频率状态.stop.unit }}
{{ state.频谱仪状态.stop.value }}
{{ state.频谱仪状态.stop.unit }}
</li>
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
<span>#CF Step</span>
@ -374,14 +471,38 @@ watchEffect(() => {
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
</ul>
<ul
v-if="state.选项卡当前显示 === E_选项卡菜单.跨度菜单列表"
class="flex h-[300px] flex-col justify-around gap-y-[4px]"
data-box="跨度菜单列表"
>
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
<span>{{ E_跨度菜单列表的项目.FullSpan }}</span>
</li>
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
<span>{{ E_跨度菜单列表的项目.ZeroSpan }}</span>
</li>
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
<span>{{ E_跨度菜单列表的项目.LastSpan }}</span>
</li>
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
</ul>
</div>
</div>
<div class="ppy-btns absolute left-[768px] top-[120px] h-[415px] !overflow-visible" data-box="机器右边按键">
<!-- 左上角. 长的 -->
<div class="flex flex-col gap-y-[18px] !overflow-visible">
<button class="ppy-btn !w-[62px]">Freq<br />Channel</button>
<button class="ppy-btn !w-[62px] opacity-0">#</button>
<button class="ppy-btn !w-[62px]" @click="state.选项卡当前显示 = E_选项卡菜单.频率菜单列表">
FREQ<br />Channel
</button>
<button class="ppy-btn !w-[62px]" @click="state.选项卡当前显示 = E_选项卡菜单.跨度菜单列表">
SPAN<br />X Scale
</button>
<!-- SPAN<br />X Scale -->
<button class="ppy-btn !w-[62px] opacity-0">#</button>
<button class="ppy-btn !w-[62px] opacity-0">#</button>