feat: 持续完善逻辑分析仪的界面
This commit is contained in:
		
							
								
								
									
										2
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -13,6 +13,7 @@ declare module 'vue' {
 | 
			
		||||
    BaseBoard: typeof import('./src/components/equipments/BaseBoard.vue')['default']
 | 
			
		||||
    BaseInputField: typeof import('./src/components/InputField/BaseInputField.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']
 | 
			
		||||
    ComponentSelector: typeof import('./src/components/LabCanvas/ComponentSelector.vue')['default']
 | 
			
		||||
    DDR: typeof import('./src/components/equipments/DDR.vue')['default']
 | 
			
		||||
@@ -67,6 +68,7 @@ declare module 'vue' {
 | 
			
		||||
    TabsTrigger: typeof import('reka-ui')['TabsTrigger']
 | 
			
		||||
    ThemeControlButton: typeof import('./src/components/ThemeControlButton.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']
 | 
			
		||||
    UploadCard: typeof import('./src/components/UploadCard.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
											
										
									
								
							
							
								
								
									
										174
									
								
								src/components/LogicAnalyzer/ChannelConfig.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								src/components/LogicAnalyzer/ChannelConfig.vue
									
									
									
									
									
										Normal file
									
								
							@@ -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>
 | 
			
		||||
							
								
								
									
										266
									
								
								src/components/LogicAnalyzer/TriggerSettings.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										266
									
								
								src/components/LogicAnalyzer/TriggerSettings.vue
									
									
									
									
									
										Normal file
									
								
							@@ -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 };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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,
 | 
			
		||||
  TutorialClient,
 | 
			
		||||
  UDPClient,
 | 
			
		||||
  LogicAnalyzerClient,
 | 
			
		||||
} from "@/APIClient";
 | 
			
		||||
 | 
			
		||||
// 支持的客户端类型联合类型
 | 
			
		||||
@@ -22,6 +23,7 @@ type SupportedClient =
 | 
			
		||||
  | PowerClient
 | 
			
		||||
  | RemoteUpdateClient
 | 
			
		||||
  | TutorialClient
 | 
			
		||||
  | LogicAnalyzerClient
 | 
			
		||||
  | UDPClient;
 | 
			
		||||
 | 
			
		||||
export class AuthManager {
 | 
			
		||||
@@ -151,6 +153,10 @@ export class AuthManager {
 | 
			
		||||
    return AuthManager.createAuthenticatedClient(UDPClient);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public static createAuthenticatedLogicAnalyzerClient(): LogicAnalyzerClient {
 | 
			
		||||
    return AuthManager.createAuthenticatedClient(LogicAnalyzerClient);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 登录函数
 | 
			
		||||
  public static async login(
 | 
			
		||||
    username: string,
 | 
			
		||||
@@ -212,11 +218,7 @@ export class AuthManager {
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      // 只有在token完全无效的情况下才清除token
 | 
			
		||||
      // 401错误表示token有效但权限不足,不应清除token
 | 
			
		||||
      if (
 | 
			
		||||
        error &&
 | 
			
		||||
        typeof error === "object" &&
 | 
			
		||||
        "status" in error
 | 
			
		||||
      ) {
 | 
			
		||||
      if (error && typeof error === "object" && "status" in error) {
 | 
			
		||||
        // 如果是403 (Forbidden) 或401 (Unauthorized),说明token有效但权限不足
 | 
			
		||||
        if (error.status === 401 || error.status === 403) {
 | 
			
		||||
          return false;
 | 
			
		||||
@@ -225,7 +227,7 @@ export class AuthManager {
 | 
			
		||||
        AuthManager.clearToken();
 | 
			
		||||
      } else {
 | 
			
		||||
        // 网络错误等,不清除token
 | 
			
		||||
        console.error('管理员权限验证失败:', error);
 | 
			
		||||
        console.error("管理员权限验证失败:", error);
 | 
			
		||||
      }
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,12 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { Zap, Settings, Layers } from "lucide-vue-next";
 | 
			
		||||
import { useEquipments } from "@/stores/equipments";
 | 
			
		||||
import { LogicalWaveFormDisplay, generateTestLogicData } from "@/components/LogicAnalyzer";
 | 
			
		||||
import { 
 | 
			
		||||
  LogicalWaveFormDisplay, 
 | 
			
		||||
  generateTestLogicData,
 | 
			
		||||
  TriggerSettings,
 | 
			
		||||
  ChannelConfig 
 | 
			
		||||
} from "@/components/LogicAnalyzer";
 | 
			
		||||
 | 
			
		||||
// 使用全局设备配置
 | 
			
		||||
const equipments = useEquipments();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user