除控制台外功能修改
This commit is contained in:
parent
310644500f
commit
b8a92220f9
@ -17,7 +17,7 @@ public sealed class MockDaq : MockDeviceBase, IDaq
|
|||||||
private double? _nextTriggerSec;
|
private double? _nextTriggerSec;
|
||||||
|
|
||||||
/// <summary>满量程电压(V)。</summary>
|
/// <summary>满量程电压(V)。</summary>
|
||||||
public double NominalVoltage { get; set; } = 28.0;
|
public double NominalVoltage { get; set; } = 5.0;
|
||||||
|
|
||||||
/// <summary>满量程电流(A)。</summary>
|
/// <summary>满量程电流(A)。</summary>
|
||||||
public double NominalCurrent { get; set; } = 1.0;
|
public double NominalCurrent { get; set; } = 1.0;
|
||||||
@ -49,6 +49,9 @@ public sealed class MockDaq : MockDeviceBase, IDaq
|
|||||||
public async Task<CurveData> CaptureAsync(
|
public async Task<CurveData> CaptureAsync(
|
||||||
int[] channels, int sampleRateHz, double durationSec, CancellationToken ct = default)
|
int[] channels, int sampleRateHz, double durationSec, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(channels);
|
||||||
|
if (channels.Length == 0)
|
||||||
|
throw new ArgumentException("At least one channel must be requested.", nameof(channels));
|
||||||
if (sampleRateHz <= 0) throw new ArgumentOutOfRangeException(nameof(sampleRateHz));
|
if (sampleRateHz <= 0) throw new ArgumentOutOfRangeException(nameof(sampleRateHz));
|
||||||
if (durationSec <= 0) throw new ArgumentOutOfRangeException(nameof(durationSec));
|
if (durationSec <= 0) throw new ArgumentOutOfRangeException(nameof(durationSec));
|
||||||
|
|
||||||
@ -57,9 +60,18 @@ public sealed class MockDaq : MockDeviceBase, IDaq
|
|||||||
await Task.Delay(simulatedDelayMs, ct).ConfigureAwait(false);
|
await Task.Delay(simulatedDelayMs, ct).ConfigureAwait(false);
|
||||||
|
|
||||||
int n = (int)Math.Round(sampleRateHz * durationSec);
|
int n = (int)Math.Round(sampleRateHz * durationSec);
|
||||||
var v = new double[n];
|
var cardVoltage = new double[n];
|
||||||
var i = new double[n];
|
var cardCurrent = new double[n];
|
||||||
double dt = 1.0 / sampleRateHz;
|
double dt = 1.0 / sampleRateHz;
|
||||||
|
int channelCount = Math.Max(1, _opts.ChannelCount);
|
||||||
|
var requestedChannels = channels.Distinct().ToArray();
|
||||||
|
foreach (int channel in requestedChannels)
|
||||||
|
{
|
||||||
|
if (channel < 0 || channel >= channelCount)
|
||||||
|
throw new ArgumentOutOfRangeException(
|
||||||
|
nameof(channels),
|
||||||
|
$"Requested channel {channel} is outside the configured PCIe8586 channel count {channelCount}.");
|
||||||
|
}
|
||||||
|
|
||||||
bool rising = NextCaptureIsRising;
|
bool rising = NextCaptureIsRising;
|
||||||
double delay = rising ? OnDelaySec : OffDelaySec;
|
double delay = rising ? OnDelaySec : OffDelaySec;
|
||||||
@ -81,7 +93,7 @@ public sealed class MockDaq : MockDeviceBase, IDaq
|
|||||||
voltage = tRel <= 0 ? NominalVoltage : NominalVoltage * Math.Exp(-tRel / TauSec);
|
voltage = tRel <= 0 ? NominalVoltage : NominalVoltage * Math.Exp(-tRel / TauSec);
|
||||||
}
|
}
|
||||||
voltage += NextGaussian() * NominalVoltage * 0.005;
|
voltage += NextGaussian() * NominalVoltage * 0.005;
|
||||||
v[k] = voltage;
|
cardVoltage[k] = voltage;
|
||||||
|
|
||||||
double current;
|
double current;
|
||||||
if (rising)
|
if (rising)
|
||||||
@ -89,16 +101,10 @@ public sealed class MockDaq : MockDeviceBase, IDaq
|
|||||||
else
|
else
|
||||||
current = tRel <= 0 ? NominalCurrent : NominalCurrent * Math.Exp(-tRel / TauSec);
|
current = tRel <= 0 ? NominalCurrent : NominalCurrent * Math.Exp(-tRel / TauSec);
|
||||||
current += NextGaussian() * NominalCurrent * 0.01;
|
current += NextGaussian() * NominalCurrent * 0.01;
|
||||||
i[k] = current;
|
cardCurrent[k] = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CurveData
|
return BuildCurve(cardVoltage, cardCurrent, sampleRateHz, triggerSec, triggerIndex: 0, requestedChannels[0]);
|
||||||
{
|
|
||||||
SampleRateHz = sampleRateHz,
|
|
||||||
TriggerTimeSec = triggerSec,
|
|
||||||
Voltage = v,
|
|
||||||
Current = i
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<double[]> ReadInstantAsync(int[] channels, CancellationToken ct = default)
|
public Task<double[]> ReadInstantAsync(int[] channels, CancellationToken ct = default)
|
||||||
@ -112,7 +118,7 @@ public sealed class MockDaq : MockDeviceBase, IDaq
|
|||||||
? DaqChannelRole.Unconfigured
|
? DaqChannelRole.Unconfigured
|
||||||
: Pcie8586Daq.ParseRole(cfg.Role);
|
: Pcie8586Daq.ParseRole(cfg.Role);
|
||||||
|
|
||||||
result[k] = role switch
|
double cardValue = role switch
|
||||||
{
|
{
|
||||||
DaqChannelRole.OutputVoltage or DaqChannelRole.InputVoltage =>
|
DaqChannelRole.OutputVoltage or DaqChannelRole.InputVoltage =>
|
||||||
NominalVoltage * (1 + (_rng.NextDouble() - 0.5) * 0.004),
|
NominalVoltage * (1 + (_rng.NextDouble() - 0.5) * 0.004),
|
||||||
@ -120,6 +126,7 @@ public sealed class MockDaq : MockDeviceBase, IDaq
|
|||||||
NominalCurrent * (1 + (_rng.NextDouble() - 0.5) * 0.02),
|
NominalCurrent * (1 + (_rng.NextDouble() - 0.5) * 0.02),
|
||||||
_ => 0
|
_ => 0
|
||||||
};
|
};
|
||||||
|
result[k] = ApplyCalibration(cardValue, cfg);
|
||||||
}
|
}
|
||||||
return Task.FromResult(result);
|
return Task.FromResult(result);
|
||||||
}
|
}
|
||||||
@ -137,7 +144,7 @@ public sealed class MockDaq : MockDeviceBase, IDaq
|
|||||||
NextCaptureIsRising = request.IsRising;
|
NextCaptureIsRising = request.IsRising;
|
||||||
await action(ct).ConfigureAwait(false);
|
await action(ct).ConfigureAwait(false);
|
||||||
_nextTriggerSec = request.PreTriggerMs / 1_000.0;
|
_nextTriggerSec = request.PreTriggerMs / 1_000.0;
|
||||||
var curve = await CaptureAsync(new[] { 0 }, sampleRate, durationSec, ct).ConfigureAwait(false);
|
var curve = await CaptureAsync(Enumerable.Range(0, Math.Max(1, _opts.ChannelCount)).ToArray(), sampleRate, durationSec, ct).ConfigureAwait(false);
|
||||||
int triggerIndex = (int)Math.Round(sampleRate * request.PreTriggerMs / 1_000.0);
|
int triggerIndex = (int)Math.Round(sampleRate * request.PreTriggerMs / 1_000.0);
|
||||||
return new CurveData
|
return new CurveData
|
||||||
{
|
{
|
||||||
@ -146,14 +153,60 @@ public sealed class MockDaq : MockDeviceBase, IDaq
|
|||||||
TriggerTimeSec = triggerIndex / (double)curve.SampleRateHz,
|
TriggerTimeSec = triggerIndex / (double)curve.SampleRateHz,
|
||||||
Voltage = curve.Voltage,
|
Voltage = curve.Voltage,
|
||||||
Current = curve.Current,
|
Current = curve.Current,
|
||||||
EngineeringChannels = new[]
|
EngineeringChannels = curve.EngineeringChannels
|
||||||
{
|
|
||||||
new CurveChannelData(0, DaqChannelRole.OutputVoltage, "模拟输出电压", "V", 1, 0, curve.Voltage),
|
|
||||||
new CurveChannelData(1, DaqChannelRole.OutputCurrent, "模拟输出电流", "A", 1, 0, curve.Current!)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CurveData BuildCurve(
|
||||||
|
double[] cardVoltage,
|
||||||
|
double[] cardCurrent,
|
||||||
|
int sampleRateHz,
|
||||||
|
double triggerSec,
|
||||||
|
int triggerIndex,
|
||||||
|
int primaryPhysicalChannel)
|
||||||
|
{
|
||||||
|
var engineering = new List<CurveChannelData>();
|
||||||
|
int channelCount = Math.Max(1, _opts.ChannelCount);
|
||||||
|
for (int channel = 0; channel < channelCount; channel++)
|
||||||
|
{
|
||||||
|
var cfg = _opts.Channels.FirstOrDefault(x => x.PhysicalChannel == channel)
|
||||||
|
?? new DaqChannelOptions { PhysicalChannel = channel, Name = $"CH{channel}" };
|
||||||
|
var role = Pcie8586Daq.ParseRole(cfg.Role);
|
||||||
|
var source = role is DaqChannelRole.OutputCurrent or DaqChannelRole.InputCurrent
|
||||||
|
? cardCurrent
|
||||||
|
: cardVoltage;
|
||||||
|
var values = source.Select(x => ApplyCalibration(x, cfg)).ToArray();
|
||||||
|
engineering.Add(new CurveChannelData(
|
||||||
|
channel, role, cfg.Name, UnitFor(role), cfg.Scale, cfg.Offset, values));
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputVoltage = engineering.Where(x => x.Role == DaqChannelRole.OutputVoltage).ToArray();
|
||||||
|
var primary = outputVoltage.Length == 1
|
||||||
|
? outputVoltage[0]
|
||||||
|
: engineering.FirstOrDefault(x => x.PhysicalChannel == primaryPhysicalChannel) ?? engineering.FirstOrDefault();
|
||||||
|
var current = engineering.FirstOrDefault(x => x.Role == DaqChannelRole.OutputCurrent)?.Samples;
|
||||||
|
|
||||||
|
return new CurveData
|
||||||
|
{
|
||||||
|
SampleRateHz = sampleRateHz,
|
||||||
|
TriggerSampleIndex = triggerIndex,
|
||||||
|
TriggerTimeSec = triggerSec,
|
||||||
|
Voltage = primary?.Samples ?? Array.Empty<double>(),
|
||||||
|
Current = current,
|
||||||
|
EngineeringChannels = engineering
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double ApplyCalibration(double value, DaqChannelOptions? cfg) =>
|
||||||
|
cfg is null ? value : value * cfg.Scale + cfg.Offset;
|
||||||
|
|
||||||
|
private static string UnitFor(DaqChannelRole role) => role switch
|
||||||
|
{
|
||||||
|
DaqChannelRole.OutputVoltage or DaqChannelRole.InputVoltage => "V",
|
||||||
|
DaqChannelRole.OutputCurrent or DaqChannelRole.InputCurrent => "A",
|
||||||
|
_ => ""
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>由 ReadInstantAsync 衍生的"电流读数"接口(基础测试页用)。</summary>
|
/// <summary>由 ReadInstantAsync 衍生的"电流读数"接口(基础测试页用)。</summary>
|
||||||
public (double volts, double amps) ReadVoltageCurrent(int channel, bool channelOn)
|
public (double volts, double amps) ReadVoltageCurrent(int channel, bool channelOn)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -7,8 +7,9 @@ namespace SSPCTester.Logic.Testing;
|
|||||||
public static class BasicTestCriteria
|
public static class BasicTestCriteria
|
||||||
{
|
{
|
||||||
public const double OnVoltageThreshold = 1.0;
|
public const double OnVoltageThreshold = 1.0;
|
||||||
public const double OffVoltageThreshold = 0.5;
|
public const double OffVoltageThreshold = 0.3;
|
||||||
public const double CurrentPresentThreshold = 0.001;
|
public const double CurrentPresentThreshold = 0.001;
|
||||||
|
public const double OffCurrentThreshold = 0.3;
|
||||||
public const int SwitchSettleDelayMs = 1_000;
|
public const int SwitchSettleDelayMs = 1_000;
|
||||||
public const int OffSettleTimeoutMs = 2_000;
|
public const int OffSettleTimeoutMs = 2_000;
|
||||||
public const int OffInitialDelayMs = 100;
|
public const int OffInitialDelayMs = 100;
|
||||||
@ -27,7 +28,7 @@ public static class BasicTestCriteria
|
|||||||
HasVoltageData(voltage) && HasCurrentData(current);
|
HasVoltageData(voltage) && HasCurrentData(current);
|
||||||
|
|
||||||
public static bool IsOffState(double voltage, double current) =>
|
public static bool IsOffState(double voltage, double current) =>
|
||||||
IsOff(voltage) && !HasCurrentData(current);
|
IsOff(voltage) && Math.Abs(current) < OffCurrentThreshold;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Waits until the channel is stably off: no voltage and no current for consecutive samples.
|
/// Waits until the channel is stably off: no voltage and no current for consecutive samples.
|
||||||
|
|||||||
@ -15,10 +15,10 @@ public sealed class BasicTestCriteriaTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(0.49, true)]
|
[InlineData(0.29, true)]
|
||||||
[InlineData(-0.49, true)]
|
[InlineData(-0.29, true)]
|
||||||
[InlineData(0.50, false)]
|
[InlineData(0.30, false)]
|
||||||
[InlineData(-0.50, false)]
|
[InlineData(-0.30, false)]
|
||||||
public void IsOff_UsesAbsoluteVoltageThreshold(double voltage, bool expected)
|
public void IsOff_UsesAbsoluteVoltageThreshold(double voltage, bool expected)
|
||||||
{
|
{
|
||||||
Assert.Equal(expected, BasicTestCriteria.IsOff(voltage));
|
Assert.Equal(expected, BasicTestCriteria.IsOff(voltage));
|
||||||
@ -35,12 +35,12 @@ public sealed class BasicTestCriteriaTests
|
|||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(0.0, 0.0, true)]
|
[InlineData(0.0, 0.0, true)]
|
||||||
[InlineData(0.49, 0.0, true)]
|
[InlineData(0.29, 0.0, true)]
|
||||||
[InlineData(-0.49, 0.0, true)]
|
[InlineData(-0.29, 0.0, true)]
|
||||||
[InlineData(0.0, 0.0005, true)]
|
[InlineData(0.0, 0.29, true)]
|
||||||
[InlineData(0.50, 0.0, false)]
|
[InlineData(0.30, 0.0, false)]
|
||||||
[InlineData(0.75, 0.0, false)]
|
[InlineData(0.75, 0.0, false)]
|
||||||
[InlineData(0.0, 0.01, false)]
|
[InlineData(0.0, 0.30, false)]
|
||||||
[InlineData(28.0, 0.0, false)]
|
[InlineData(28.0, 0.0, false)]
|
||||||
public void IsOffState_RequiresNoVoltageAndNoCurrent(double voltage, double current, bool expected)
|
public void IsOffState_RequiresNoVoltageAndNoCurrent(double voltage, double current, bool expected)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -56,6 +56,51 @@ public sealed class DaqIntegrationTests
|
|||||||
Assert.False(await sspc.GetChannelStateAsync(3));
|
Assert.False(await sspc.GetChannelStateAsync(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task MockDaq_AppliesScaleAndOffset()
|
||||||
|
{
|
||||||
|
var options = new DeviceOptions();
|
||||||
|
options.Daq.ClockDivider = 100_000;
|
||||||
|
options.Daq.ChannelCount = 2;
|
||||||
|
options.Daq.Channels[0].Role = nameof(DaqChannelRole.OutputVoltage);
|
||||||
|
options.Daq.Channels[0].Name = "Vout";
|
||||||
|
options.Daq.Channels[0].Scale = 2;
|
||||||
|
options.Daq.Channels[0].Offset = 1;
|
||||||
|
options.Daq.Channels[0].IsCalibrated = true;
|
||||||
|
options.Daq.Channels[1].Role = nameof(DaqChannelRole.OutputCurrent);
|
||||||
|
options.Daq.Channels[1].Name = "Iout";
|
||||||
|
options.Daq.Channels[1].Scale = 3;
|
||||||
|
options.Daq.Channels[1].Offset = -1;
|
||||||
|
options.Daq.Channels[1].IsCalibrated = true;
|
||||||
|
var daq = new MockDaq(Options.Create(options), NullLogger<MockDaq>.Instance)
|
||||||
|
{
|
||||||
|
NominalVoltage = 10,
|
||||||
|
NominalCurrent = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
var curve = await daq.CaptureAroundActionAsync(
|
||||||
|
new DaqActionCaptureRequest(10, 40, true),
|
||||||
|
_ => Task.CompletedTask);
|
||||||
|
var instant = await daq.ReadInstantAsync(new[] { 0, 1 });
|
||||||
|
|
||||||
|
Assert.True(curve.Voltage.Max() > 20);
|
||||||
|
Assert.True(curve.Current!.Max() > 1.8);
|
||||||
|
Assert.Contains(curve.EngineeringChannels, x =>
|
||||||
|
x.PhysicalChannel == 0 &&
|
||||||
|
x.Role == DaqChannelRole.OutputVoltage &&
|
||||||
|
x.Name == "Vout" &&
|
||||||
|
x.Scale == 2 &&
|
||||||
|
x.Offset == 1);
|
||||||
|
Assert.Contains(curve.EngineeringChannels, x =>
|
||||||
|
x.PhysicalChannel == 1 &&
|
||||||
|
x.Role == DaqChannelRole.OutputCurrent &&
|
||||||
|
x.Name == "Iout" &&
|
||||||
|
x.Scale == 3 &&
|
||||||
|
x.Offset == -1);
|
||||||
|
Assert.InRange(instant[0], 20.9, 21.1);
|
||||||
|
Assert.InRange(instant[1], 1.9, 2.1);
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(1000, 100_000)]
|
[InlineData(1000, 100_000)]
|
||||||
[InlineData(100, 1_000_000)]
|
[InlineData(100, 1_000_000)]
|
||||||
|
|||||||
@ -298,6 +298,36 @@ public partial class CurveTestViewModel : ObservableObject
|
|||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private Task CaptureFalling() => CaptureSingleCurveAsync(CurveCaptureKind.Falling);
|
private Task CaptureFalling() => CaptureSingleCurveAsync(CurveCaptureKind.Falling);
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Clear()
|
||||||
|
{
|
||||||
|
foreach (var row in Rows)
|
||||||
|
{
|
||||||
|
row.OnTimeMs = 0;
|
||||||
|
row.RiseTimeMs = 0;
|
||||||
|
row.OffTimeMs = 0;
|
||||||
|
row.FallTimeMs = 0;
|
||||||
|
row.RisingWaveformPath = null;
|
||||||
|
row.FallingWaveformPath = null;
|
||||||
|
row.ViewStartMs = null;
|
||||||
|
row.ViewEndMs = null;
|
||||||
|
row.RisingViewStartMs = null;
|
||||||
|
row.RisingViewEndMs = null;
|
||||||
|
row.FallingViewStartMs = null;
|
||||||
|
row.FallingViewEndMs = null;
|
||||||
|
row.Status = TestStatus.Untested;
|
||||||
|
}
|
||||||
|
|
||||||
|
RisingCurve = null;
|
||||||
|
FallingCurve = null;
|
||||||
|
RisingViewStartMs = null;
|
||||||
|
RisingViewEndMs = null;
|
||||||
|
FallingViewStartMs = null;
|
||||||
|
FallingViewEndMs = null;
|
||||||
|
SaveProjectQuietly();
|
||||||
|
_log.Add(UiLogLevel.Info, "开启与关断曲线结果已清空。");
|
||||||
|
}
|
||||||
|
|
||||||
private async Task CaptureSingleCurveAsync(CurveCaptureKind kind)
|
private async Task CaptureSingleCurveAsync(CurveCaptureKind kind)
|
||||||
{
|
{
|
||||||
if (Project == null || Busy) return;
|
if (Project == null || Busy) return;
|
||||||
|
|||||||
@ -181,6 +181,23 @@ public partial class PowerTestViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Clear()
|
||||||
|
{
|
||||||
|
foreach (var row in Rows)
|
||||||
|
{
|
||||||
|
row.Vin = 0;
|
||||||
|
row.Iin = 0;
|
||||||
|
row.Vout = 0;
|
||||||
|
row.Iout = 0;
|
||||||
|
row.MeasuredPowerOut = null;
|
||||||
|
row.Status = TestStatus.Untested;
|
||||||
|
}
|
||||||
|
|
||||||
|
Current = Rows.FirstOrDefault();
|
||||||
|
_log.Add(UiLogLevel.Info, "功率损耗结果已清空。");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>解析用于输入端电压的高速采集卡通道(取已标定的电压通道,优先 OutputVoltage)。</summary>
|
/// <summary>解析用于输入端电压的高速采集卡通道(取已标定的电压通道,优先 OutputVoltage)。</summary>
|
||||||
private static int ResolveDaqVoltageChannel(DaqOptions options)
|
private static int ResolveDaqVoltageChannel(DaqOptions options)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
<RowDefinition Height="2*" MinHeight="180" />
|
<RowDefinition Height="2*" MinHeight="180" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<TextBlock Text="开启与关断曲线(覆盖指标 1.1–1.6)" FontSize="{StaticResource FsH1}" FontWeight="Bold" Margin="0,0,0,12" />
|
<TextBlock Text="开启与关断曲线" FontSize="{StaticResource FsH1}" FontWeight="Bold" Margin="0,0,0,12" />
|
||||||
|
|
||||||
<Grid Grid.Row="1">
|
<Grid Grid.Row="1">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
@ -144,7 +144,17 @@
|
|||||||
|
|
||||||
<Border Style="{StaticResource Card}" Margin="0,0,12,0">
|
<Border Style="{StaticResource Card}" Margin="0,0,12,0">
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
<TextBlock DockPanel.Dock="Top" Style="{StaticResource CardTitle}" Text="各通道时间参数" />
|
<Grid DockPanel.Dock="Top" Margin="0,0,0,8">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Style="{StaticResource CardTitle}" Text="各通道时间参数" />
|
||||||
|
<Button Grid.Column="1"
|
||||||
|
Content="清空结果"
|
||||||
|
Command="{Binding ClearCommand}"
|
||||||
|
IsEnabled="{Binding Busy, Converter={StaticResource InverseBoolConverter}}" />
|
||||||
|
</Grid>
|
||||||
<DataGrid ItemsSource="{Binding Rows}"
|
<DataGrid ItemsSource="{Binding Rows}"
|
||||||
SelectedItem="{Binding SelectedRow, Mode=TwoWay}">
|
SelectedItem="{Binding SelectedRow, Mode=TwoWay}">
|
||||||
<DataGrid.Columns>
|
<DataGrid.Columns>
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
<RowDefinition Height="3*" MinHeight="220" />
|
<RowDefinition Height="3*" MinHeight="220" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<TextBlock Text="功率损耗(采集输入/输出两端数据)" FontSize="{StaticResource FsH1}" FontWeight="Bold" Margin="0,0,0,12" />
|
<TextBlock Text="功率损耗" FontSize="{StaticResource FsH1}" FontWeight="Bold" Margin="0,0,0,12" />
|
||||||
|
|
||||||
<Grid Grid.Row="1">
|
<Grid Grid.Row="1">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
@ -178,7 +178,17 @@
|
|||||||
|
|
||||||
<Border Style="{StaticResource Card}" Margin="0,0,12,0">
|
<Border Style="{StaticResource Card}" Margin="0,0,12,0">
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
<TextBlock DockPanel.Dock="Top" Style="{StaticResource CardTitle}" Text="各通道汇总" />
|
<Grid DockPanel.Dock="Top" Margin="0,0,0,8">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Style="{StaticResource CardTitle}" Text="各通道汇总" />
|
||||||
|
<Button Grid.Column="1"
|
||||||
|
Content="清空结果"
|
||||||
|
Command="{Binding ClearCommand}"
|
||||||
|
IsEnabled="{Binding CanOperate}" />
|
||||||
|
</Grid>
|
||||||
<DataGrid ItemsSource="{Binding Rows}">
|
<DataGrid ItemsSource="{Binding Rows}">
|
||||||
<DataGrid.Columns>
|
<DataGrid.Columns>
|
||||||
<DataGridTextColumn Header="通道" Width="60">
|
<DataGridTextColumn Header="通道" Width="60">
|
||||||
|
|||||||
@ -15,7 +15,6 @@
|
|||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<TextBlock Text="{Binding Project.Name, StringFormat='项目:{0}'}" FontSize="{StaticResource FsH1}" FontWeight="Bold" />
|
<TextBlock Text="{Binding Project.Name, StringFormat='项目:{0}'}" FontSize="{StaticResource FsH1}" FontWeight="Bold" />
|
||||||
<TextBlock Text="填写被测件信息并选择测试项。" Foreground="{StaticResource TextSecondaryBrush}" Margin="0,4,0,0" />
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
<RowDefinition Height="2*" MinHeight="200" />
|
<RowDefinition Height="2*" MinHeight="200" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<TextBlock Text="保护功能(覆盖指标 11/14/15/17/19/21/22/23)" FontSize="{StaticResource FsH1}" FontWeight="Bold" Margin="0,0,0,8" />
|
<TextBlock Text="保护功能" FontSize="{StaticResource FsH1}" FontWeight="Bold" Margin="0,0,0,8" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,10 @@
|
|||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Text="测试报告" FontSize="{StaticResource FsH1}" FontWeight="Bold" />
|
<TextBlock FontSize="{StaticResource FsH1}" FontWeight="Bold">
|
||||||
|
<Run Text="测试报告:" />
|
||||||
|
<Run Text="{Binding Project.Name, Mode=OneWay}" />
|
||||||
|
</TextBlock>
|
||||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
||||||
<ComboBox Width="130"
|
<ComboBox Width="130"
|
||||||
Margin="0,0,8,0"
|
Margin="0,0,8,0"
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DataContext="{d:DesignInstance Type=vm:TestHostViewModel}">
|
d:DataContext="{d:DesignInstance Type=vm:TestHostViewModel}">
|
||||||
<Border Background="{StaticResource BgSurfaceBrush}" BorderBrush="{StaticResource BorderSubtleBrush}" BorderThickness="0,0,0,1">
|
<Border Background="{StaticResource BgSurfaceBrush}" BorderBrush="{StaticResource BorderSubtleBrush}" BorderThickness="0,0,0,1">
|
||||||
|
<Grid>
|
||||||
<TabControl x:Name="Tabs">
|
<TabControl x:Name="Tabs">
|
||||||
<TabItem Header="基础测试">
|
<TabItem Header="基础测试">
|
||||||
<ContentControl Content="{Binding Basic}" />
|
<ContentControl Content="{Binding Basic}" />
|
||||||
@ -21,5 +22,16 @@
|
|||||||
<ContentControl Content="{Binding Protect}" />
|
<ContentControl Content="{Binding Protect}" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</TabControl>
|
</TabControl>
|
||||||
|
|
||||||
|
<TextBlock Text="{Binding Project.Name, StringFormat='当前项目:{0}'}"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
Margin="0,10,20,0"
|
||||||
|
Foreground="{StaticResource TextSecondaryBrush}"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
TextTrimming="CharacterEllipsis"
|
||||||
|
MaxWidth="420"
|
||||||
|
IsHitTestVisible="False" />
|
||||||
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user