feat: 持续完善逻辑分析仪的界面
This commit is contained in:
parent
4d6c06a0e0
commit
c9fc6961fa
|
@ -13,6 +13,7 @@ declare module 'vue' {
|
||||||
BaseBoard: typeof import('./src/components/equipments/BaseBoard.vue')['default']
|
BaseBoard: typeof import('./src/components/equipments/BaseBoard.vue')['default']
|
||||||
BaseInputField: typeof import('./src/components/InputField/BaseInputField.vue')['default']
|
BaseInputField: typeof import('./src/components/InputField/BaseInputField.vue')['default']
|
||||||
Canvas: typeof import('./src/components/Canvas.vue')['default']
|
Canvas: typeof import('./src/components/Canvas.vue')['default']
|
||||||
|
ChannelConfig: typeof import('./src/components/LogicAnalyzer/ChannelConfig.vue')['default']
|
||||||
CollapsibleSection: typeof import('./src/components/CollapsibleSection.vue')['default']
|
CollapsibleSection: typeof import('./src/components/CollapsibleSection.vue')['default']
|
||||||
ComponentSelector: typeof import('./src/components/LabCanvas/ComponentSelector.vue')['default']
|
ComponentSelector: typeof import('./src/components/LabCanvas/ComponentSelector.vue')['default']
|
||||||
DDR: typeof import('./src/components/equipments/DDR.vue')['default']
|
DDR: typeof import('./src/components/equipments/DDR.vue')['default']
|
||||||
|
@ -67,6 +68,7 @@ declare module 'vue' {
|
||||||
TabsTrigger: typeof import('reka-ui')['TabsTrigger']
|
TabsTrigger: typeof import('reka-ui')['TabsTrigger']
|
||||||
ThemeControlButton: typeof import('./src/components/ThemeControlButton.vue')['default']
|
ThemeControlButton: typeof import('./src/components/ThemeControlButton.vue')['default']
|
||||||
ThemeControlToggle: typeof import('./src/components/ThemeControlToggle.vue')['default']
|
ThemeControlToggle: typeof import('./src/components/ThemeControlToggle.vue')['default']
|
||||||
|
TriggerSettings: typeof import('./src/components/LogicAnalyzer/TriggerSettings.vue')['default']
|
||||||
TutorialCarousel: typeof import('./src/components/TutorialCarousel.vue')['default']
|
TutorialCarousel: typeof import('./src/components/TutorialCarousel.vue')['default']
|
||||||
UploadCard: typeof import('./src/components/UploadCard.vue')['default']
|
UploadCard: typeof import('./src/components/UploadCard.vue')['default']
|
||||||
WaveformDisplay: typeof import('./src/components/Oscilloscope/WaveformDisplay.vue')['default']
|
WaveformDisplay: typeof import('./src/components/Oscilloscope/WaveformDisplay.vue')['default']
|
||||||
|
|
7615
src/APIClient.ts
7615
src/APIClient.ts
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,174 @@
|
||||||
|
<template>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<!-- 通道状态概览 -->
|
||||||
|
<div class="stats stats-horizontal bg-base-100 shadow flex justify-between">
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-title">总通道数</div>
|
||||||
|
<div class="stat-value text-primary">8</div>
|
||||||
|
<div class="stat-desc">逻辑分析仪通道</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-title">启用通道</div>
|
||||||
|
<div class="stat-value text-success">{{ enabledChannelCount }}</div>
|
||||||
|
<div class="stat-desc">当前激活通道</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-title">采样率</div>
|
||||||
|
<div class="stat-value text-info">100MHz</div>
|
||||||
|
<div class="stat-desc">最大采样频率</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 通道配置列表 -->
|
||||||
|
<div class="space-y-2">
|
||||||
|
<div class="flex items-center justify-between p-2 bg-base-300 rounded-lg">
|
||||||
|
<span class="font-medium">通道</span>
|
||||||
|
<span class="font-medium">启用</span>
|
||||||
|
<span class="font-medium">标签</span>
|
||||||
|
<span class="font-medium">颜色</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-for="(channel, index) in channels"
|
||||||
|
:key="index"
|
||||||
|
class="flex items-center justify-between p-3 bg-base-200 rounded-lg hover:bg-base-300 transition-colors"
|
||||||
|
>
|
||||||
|
<!-- 通道编号 -->
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="font-mono font-medium w-12">CH{{ index }}</span>
|
||||||
|
<div
|
||||||
|
class="w-3 h-3 rounded-full border-2 border-white shadow-sm"
|
||||||
|
:style="{ backgroundColor: channel.color }"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 启用开关 -->
|
||||||
|
<div class="form-control">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
v-model="channel.enabled"
|
||||||
|
class="toggle toggle-sm toggle-primary"
|
||||||
|
@change="updateChannelStatus(index)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 通道标签 -->
|
||||||
|
<div class="form-control w-32">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
v-model="channel.label"
|
||||||
|
:placeholder="`通道 ${index}`"
|
||||||
|
class="input input-sm input-bordered w-full"
|
||||||
|
:disabled="!channel.enabled"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 颜色选择 -->
|
||||||
|
<div class="form-control">
|
||||||
|
<input
|
||||||
|
type="color"
|
||||||
|
v-model="channel.color"
|
||||||
|
class="w-8 h-8 rounded border-2 border-base-300 cursor-pointer"
|
||||||
|
:disabled="!channel.enabled"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 批量操作 -->
|
||||||
|
<div class="flex gap-2 pt-4">
|
||||||
|
<button @click="enableAllChannels" class="btn btn-primary btn-sm">
|
||||||
|
全部启用
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button @click="disableAllChannels" class="btn btn-outline btn-sm">
|
||||||
|
全部禁用
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button @click="resetChannelLabels" class="btn btn-outline btn-sm">
|
||||||
|
重置标签
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, reactive } from "vue";
|
||||||
|
|
||||||
|
// 通道接口定义
|
||||||
|
interface Channel {
|
||||||
|
enabled: boolean;
|
||||||
|
label: string;
|
||||||
|
color: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预设配置接口
|
||||||
|
interface Preset {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
channels: Partial<Channel>[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认颜色数组
|
||||||
|
const defaultColors = [
|
||||||
|
"#FF5733",
|
||||||
|
"#33FF57",
|
||||||
|
"#3357FF",
|
||||||
|
"#FF33F5",
|
||||||
|
"#F5FF33",
|
||||||
|
"#33FFF5",
|
||||||
|
"#FF8C33",
|
||||||
|
"#8C33FF",
|
||||||
|
];
|
||||||
|
|
||||||
|
// 通道配置
|
||||||
|
const channels = reactive<Channel[]>(
|
||||||
|
Array.from({ length: 8 }, (_, index) => ({
|
||||||
|
enabled: false,
|
||||||
|
label: `CH${index}`,
|
||||||
|
color: defaultColors[index],
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 计算启用的通道数量
|
||||||
|
const enabledChannelCount = computed(
|
||||||
|
() => channels.filter((channel) => channel.enabled).length,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 更新通道状态
|
||||||
|
const updateChannelStatus = (index: number) => {
|
||||||
|
console.log(`通道 ${index} 状态更新:`, channels[index].enabled);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 启用所有通道
|
||||||
|
const enableAllChannels = () => {
|
||||||
|
channels.forEach((channel) => {
|
||||||
|
channel.enabled = true;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 禁用所有通道
|
||||||
|
const disableAllChannels = () => {
|
||||||
|
channels.forEach((channel) => {
|
||||||
|
channel.enabled = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置通道标签
|
||||||
|
const resetChannelLabels = () => {
|
||||||
|
channels.forEach((channel, index) => {
|
||||||
|
channel.label = `CH${index}`;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 应用预设配置
|
||||||
|
const applyPreset = (preset: Preset) => {
|
||||||
|
preset.channels.forEach((presetChannel, index) => {
|
||||||
|
if (index < channels.length && presetChannel) {
|
||||||
|
Object.assign(channels[index], presetChannel);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,266 @@
|
||||||
|
<template>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<!-- 全局触发模式配置 -->
|
||||||
|
<div class="form-control">
|
||||||
|
<label class="label">
|
||||||
|
<span class="label-text font-medium">全局触发模式</span>
|
||||||
|
</label>
|
||||||
|
<div class="grid grid-cols-2 md:grid-cols-4 gap-2">
|
||||||
|
<button
|
||||||
|
v-for="mode in globalModes"
|
||||||
|
:key="mode.value"
|
||||||
|
@click="setGlobalMode(mode.value)"
|
||||||
|
:class="[
|
||||||
|
'btn btn-sm',
|
||||||
|
currentGlobalMode === mode.value ? 'btn-primary' : 'btn-outline',
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
{{ mode.label }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
<span class="label-text-alt text-gray-500">
|
||||||
|
选择多路信号触发条件的逻辑组合方式
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 信号触发配置 -->
|
||||||
|
<div class="form-control">
|
||||||
|
<label class="label">
|
||||||
|
<span class="label-text font-medium">信号触发配置</span>
|
||||||
|
</label>
|
||||||
|
<div class="space-y-2">
|
||||||
|
<div
|
||||||
|
v-for="(signal, index) in signalConfigs"
|
||||||
|
:key="index"
|
||||||
|
class="flex items-center gap-2 p-3 bg-base-200 rounded-lg"
|
||||||
|
>
|
||||||
|
<span class="text-sm font-medium w-16">CH{{ index }}</span>
|
||||||
|
|
||||||
|
<!-- 操作符选择 -->
|
||||||
|
<select
|
||||||
|
v-model="signal.operator"
|
||||||
|
class="select select-sm select-bordered w-32"
|
||||||
|
>
|
||||||
|
<option v-for="op in operators" :key="op.value" :value="op.value">
|
||||||
|
{{ op.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 信号值选择 -->
|
||||||
|
<select
|
||||||
|
v-model="signal.value"
|
||||||
|
class="select select-sm select-bordered w-32"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-for="val in signalValues"
|
||||||
|
:key="val.value"
|
||||||
|
:value="val.value"
|
||||||
|
>
|
||||||
|
{{ val.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 启用/禁用开关 -->
|
||||||
|
<div class="form-control">
|
||||||
|
<label class="label cursor-pointer gap-2">
|
||||||
|
<span class="label-text text-sm">启用</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
v-model="signal.enabled"
|
||||||
|
class="toggle toggle-sm toggle-primary"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<div class="flex gap-2 pt-4">
|
||||||
|
<button
|
||||||
|
@click="applyConfiguration"
|
||||||
|
:disabled="isApplying"
|
||||||
|
class="btn btn-primary btn-sm"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-if="isApplying"
|
||||||
|
class="loading loading-spinner loading-sm"
|
||||||
|
></span>
|
||||||
|
应用配置
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button @click="resetConfiguration" class="btn btn-outline btn-sm">
|
||||||
|
重置
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 状态指示 -->
|
||||||
|
<div
|
||||||
|
v-if="lastApplyResult"
|
||||||
|
class="alert alert-sm"
|
||||||
|
:class="lastApplyResult.success ? 'alert-success' : 'alert-error'"
|
||||||
|
>
|
||||||
|
<span>{{ lastApplyResult.message }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, computed } from "vue";
|
||||||
|
import { useEquipments } from "@/stores/equipments";
|
||||||
|
import {
|
||||||
|
CaptureConfig,
|
||||||
|
LogicAnalyzerClient,
|
||||||
|
GlobalCaptureMode,
|
||||||
|
SignalOperator,
|
||||||
|
SignalValue,
|
||||||
|
type SignalTriggerConfig,
|
||||||
|
} from "@/APIClient";
|
||||||
|
import { AuthManager } from "@/utils/AuthManager";
|
||||||
|
|
||||||
|
// 使用设备配置
|
||||||
|
const equipments = useEquipments();
|
||||||
|
|
||||||
|
// 当前全局模式
|
||||||
|
const currentGlobalMode = ref<GlobalCaptureMode>(GlobalCaptureMode.AND);
|
||||||
|
|
||||||
|
// 加载状态
|
||||||
|
const isApplying = ref(false);
|
||||||
|
const lastApplyResult = ref<{ success: boolean; message: string } | null>(null);
|
||||||
|
|
||||||
|
// 全局模式选项
|
||||||
|
const globalModes = [
|
||||||
|
{
|
||||||
|
value: GlobalCaptureMode.AND,
|
||||||
|
label: "AND",
|
||||||
|
description: "所有条件都满足时触发",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: GlobalCaptureMode.OR,
|
||||||
|
label: "OR",
|
||||||
|
description: "任一条件满足时触发",
|
||||||
|
},
|
||||||
|
{ value: GlobalCaptureMode.NAND, label: "NAND", description: "AND的非" },
|
||||||
|
{ value: GlobalCaptureMode.NOR, label: "NOR", description: "OR的非" },
|
||||||
|
];
|
||||||
|
|
||||||
|
// 操作符选项
|
||||||
|
const operators = [
|
||||||
|
{ value: SignalOperator.Equal, label: "=" },
|
||||||
|
{ value: SignalOperator.NotEqual, label: "≠" },
|
||||||
|
{ value: SignalOperator.LessThan, label: "<" },
|
||||||
|
{ value: SignalOperator.LessThanOrEqual, label: "≤" },
|
||||||
|
{ value: SignalOperator.GreaterThan, label: ">" },
|
||||||
|
{ value: SignalOperator.GreaterThanOrEqual, label: "≥" },
|
||||||
|
];
|
||||||
|
|
||||||
|
// 信号值选项
|
||||||
|
const signalValues = [
|
||||||
|
{ value: SignalValue.Logic0, label: "0" },
|
||||||
|
{ value: SignalValue.Logic1, label: "1" },
|
||||||
|
{ value: SignalValue.NotCare, label: "X" },
|
||||||
|
{ value: SignalValue.Rise, label: "↑" },
|
||||||
|
{ value: SignalValue.Fall, label: "↓" },
|
||||||
|
{ value: SignalValue.RiseOrFall, label: "↕" },
|
||||||
|
{ value: SignalValue.NoChange, label: "—" },
|
||||||
|
{ value: SignalValue.SomeNumber, label: "#" },
|
||||||
|
];
|
||||||
|
|
||||||
|
// 8个信号通道的配置
|
||||||
|
const signalConfigs = reactive(
|
||||||
|
Array.from({ length: 8 }, (_, index) => ({
|
||||||
|
signalIndex: index,
|
||||||
|
operator: SignalOperator.Equal,
|
||||||
|
value: SignalValue.Logic1,
|
||||||
|
enabled: false,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 设置全局触发模式
|
||||||
|
const setGlobalMode = async (mode: GlobalCaptureMode) => {
|
||||||
|
try {
|
||||||
|
const client = AuthManager.createAuthenticatedLogicAnalyzerClient();
|
||||||
|
const success = await client.setGlobalTrigMode(mode);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
currentGlobalMode.value = mode;
|
||||||
|
lastApplyResult.value = {
|
||||||
|
success: true,
|
||||||
|
message: `全局触发模式已设置为 ${globalModes.find((m) => m.value === mode)?.label}`,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
throw new Error("设置失败");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("设置全局触发模式失败:", error);
|
||||||
|
lastApplyResult.value = {
|
||||||
|
success: false,
|
||||||
|
message: "设置全局触发模式失败",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 应用完整配置
|
||||||
|
const applyConfiguration = async () => {
|
||||||
|
isApplying.value = true;
|
||||||
|
lastApplyResult.value = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const client = AuthManager.createAuthenticatedLogicAnalyzerClient();
|
||||||
|
|
||||||
|
// 准备配置数据
|
||||||
|
const enabledSignals = signalConfigs.filter((signal) => signal.enabled);
|
||||||
|
const config = new CaptureConfig({
|
||||||
|
globalMode: currentGlobalMode.value,
|
||||||
|
signalConfigs: enabledSignals.map(
|
||||||
|
(signal) =>
|
||||||
|
({
|
||||||
|
signalIndex: signal.signalIndex,
|
||||||
|
operator: signal.operator,
|
||||||
|
value: signal.value,
|
||||||
|
}) as SignalTriggerConfig,
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
// 发送配置
|
||||||
|
const success = await client.configureCapture(config);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
lastApplyResult.value = {
|
||||||
|
success: true,
|
||||||
|
message: `配置已成功应用,启用了 ${enabledSignals.length} 个通道`,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
throw new Error("应用配置失败");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("应用配置失败:", error);
|
||||||
|
lastApplyResult.value = {
|
||||||
|
success: false,
|
||||||
|
message: "应用配置失败,请检查设备连接",
|
||||||
|
};
|
||||||
|
} finally {
|
||||||
|
isApplying.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置配置
|
||||||
|
const resetConfiguration = () => {
|
||||||
|
currentGlobalMode.value = GlobalCaptureMode.AND;
|
||||||
|
signalConfigs.forEach((signal) => {
|
||||||
|
signal.operator = SignalOperator.Equal;
|
||||||
|
signal.value = SignalValue.Logic1;
|
||||||
|
signal.enabled = false;
|
||||||
|
});
|
||||||
|
lastApplyResult.value = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 清除状态消息
|
||||||
|
setTimeout(() => {
|
||||||
|
if (lastApplyResult.value) {
|
||||||
|
lastApplyResult.value = null;
|
||||||
|
}
|
||||||
|
}, 5000);
|
||||||
|
</script>
|
|
@ -73,4 +73,6 @@ function generateTestLogicData(): LogicDataType {
|
||||||
return { x, y, xUnit: "ms", channelNames };
|
return { x, y, xUnit: "ms", channelNames };
|
||||||
}
|
}
|
||||||
|
|
||||||
export { LogicalWaveFormDisplay, generateTestLogicData, type LogicDataType };
|
export { LogicalWaveFormDisplay, generateTestLogicData, type LogicDataType };
|
||||||
|
export { default as TriggerSettings } from './TriggerSettings.vue'
|
||||||
|
export { default as ChannelConfig } from './ChannelConfig.vue'
|
|
@ -9,6 +9,7 @@ import {
|
||||||
RemoteUpdateClient,
|
RemoteUpdateClient,
|
||||||
TutorialClient,
|
TutorialClient,
|
||||||
UDPClient,
|
UDPClient,
|
||||||
|
LogicAnalyzerClient,
|
||||||
} from "@/APIClient";
|
} from "@/APIClient";
|
||||||
|
|
||||||
// 支持的客户端类型联合类型
|
// 支持的客户端类型联合类型
|
||||||
|
@ -22,6 +23,7 @@ type SupportedClient =
|
||||||
| PowerClient
|
| PowerClient
|
||||||
| RemoteUpdateClient
|
| RemoteUpdateClient
|
||||||
| TutorialClient
|
| TutorialClient
|
||||||
|
| LogicAnalyzerClient
|
||||||
| UDPClient;
|
| UDPClient;
|
||||||
|
|
||||||
export class AuthManager {
|
export class AuthManager {
|
||||||
|
@ -151,6 +153,10 @@ export class AuthManager {
|
||||||
return AuthManager.createAuthenticatedClient(UDPClient);
|
return AuthManager.createAuthenticatedClient(UDPClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static createAuthenticatedLogicAnalyzerClient(): LogicAnalyzerClient {
|
||||||
|
return AuthManager.createAuthenticatedClient(LogicAnalyzerClient);
|
||||||
|
}
|
||||||
|
|
||||||
// 登录函数
|
// 登录函数
|
||||||
public static async login(
|
public static async login(
|
||||||
username: string,
|
username: string,
|
||||||
|
@ -212,11 +218,7 @@ export class AuthManager {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// 只有在token完全无效的情况下才清除token
|
// 只有在token完全无效的情况下才清除token
|
||||||
// 401错误表示token有效但权限不足,不应清除token
|
// 401错误表示token有效但权限不足,不应清除token
|
||||||
if (
|
if (error && typeof error === "object" && "status" in error) {
|
||||||
error &&
|
|
||||||
typeof error === "object" &&
|
|
||||||
"status" in error
|
|
||||||
) {
|
|
||||||
// 如果是403 (Forbidden) 或401 (Unauthorized),说明token有效但权限不足
|
// 如果是403 (Forbidden) 或401 (Unauthorized),说明token有效但权限不足
|
||||||
if (error.status === 401 || error.status === 403) {
|
if (error.status === 401 || error.status === 403) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -225,7 +227,7 @@ export class AuthManager {
|
||||||
AuthManager.clearToken();
|
AuthManager.clearToken();
|
||||||
} else {
|
} else {
|
||||||
// 网络错误等,不清除token
|
// 网络错误等,不清除token
|
||||||
console.error('管理员权限验证失败:', error);
|
console.error("管理员权限验证失败:", error);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,12 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Zap, Settings, Layers } from "lucide-vue-next";
|
import { Zap, Settings, Layers } from "lucide-vue-next";
|
||||||
import { useEquipments } from "@/stores/equipments";
|
import { useEquipments } from "@/stores/equipments";
|
||||||
import { LogicalWaveFormDisplay, generateTestLogicData } from "@/components/LogicAnalyzer";
|
import {
|
||||||
|
LogicalWaveFormDisplay,
|
||||||
|
generateTestLogicData,
|
||||||
|
TriggerSettings,
|
||||||
|
ChannelConfig
|
||||||
|
} from "@/components/LogicAnalyzer";
|
||||||
|
|
||||||
// 使用全局设备配置
|
// 使用全局设备配置
|
||||||
const equipments = useEquipments();
|
const equipments = useEquipments();
|
||||||
|
|
Loading…
Reference in New Issue