提交用户部分代码

This commit is contained in:
chfei committed 2026-11-13 15:51:16 +08:00
1 parent 9b9e4cbd82
commit 127fc22de5
26 files changed
+1110 -206

No files matched your search

@@ -24,7 +24,7 @@ public sealed class FolderConfig : IFolderConfig
/// <summary>当前用户的数据根目录:%LOCALAPPDATA%\Store.Management。</summary>
public static string AppFolder => Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), AppName);
//, MAX.Core.Cryptography.MD5Helper.Md5_32(ExeFolder)
public static string ConfigFolder => Path.Combine(AppFolder, "Config");
public static string DataFolder => Path.Combine(AppFolder, "Data");
public static string LoggingFolder => Path.Combine(AppFolder, "Logs");
@@ -602,7 +602,6 @@
HorizontalAlignment="Center"
VerticalAlignment="Center"
HorizontalContentAlignment="Center"
AutomationProperties.Name="全选行"
Command="{x:Static ext:DataGridEx.ToggleSelectAllCommand}"
CommandTarget="{Binding RelativeSource={RelativeSource AncestorType={x:Type ext:DataGridEx}}}"
IsChecked="{Binding AreAllRowsSelected, RelativeSource={RelativeSource AncestorType={x:Type ext:DataGridEx}}, Mode=OneWay}">
@@ -992,7 +991,6 @@
<CheckBox
HorizontalAlignment="Center"
VerticalAlignment="Center"
AutomationProperties.Name="选择行"
IsChecked="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=DataGridRow}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource DataGridExCheckBoxStyle}" />
</Border>
@@ -5,7 +5,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Store.Management.Framework.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="DialogWindow"
Title="{Binding Title}"
Width="800"
Height="450"
mc:Ignorable="d">
@@ -0,0 +1,127 @@
using MAX.Common.Helpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace Store.Management.Framework.Controls
{
internal class HorizontalIconText : Control
{
public string Icon
{
get => (string)GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(
nameof(Icon),
typeof(string),
typeof(HorizontalIconText),
new PropertyMetadata(null, OnOnIconChanged)
);
public bool ShowIcon
{
get => (bool)GetValue(ShowIconProperty);
private set => SetValue(ShowIconPropertyKey, value);
}
private static readonly DependencyPropertyKey ShowIconPropertyKey = DependencyProperty.RegisterReadOnly(
nameof(ShowIcon),
typeof(bool),
typeof(HorizontalIconText),
new PropertyMetadata(false)
);
public static readonly DependencyProperty ShowIconProperty = ShowIconPropertyKey.DependencyProperty;
public bool ShowSpace
{
get => (bool)GetValue(ShowSpaceProperty);
private set => SetValue(ShowSpacePropertyKey, value);
}
private static readonly DependencyPropertyKey ShowSpacePropertyKey = DependencyProperty.RegisterReadOnly(
nameof(ShowSpace),
typeof(bool),
typeof(HorizontalIconText),
new PropertyMetadata(true)
);
public static readonly DependencyProperty ShowSpaceProperty = ShowSpacePropertyKey.DependencyProperty;
public string Text
{
get => (string)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
nameof(Text),
typeof(string),
typeof(HorizontalIconText),
new PropertyMetadata(string.Empty)
);
public double IconSize
{
get => (double)GetValue(IconSizeProperty);
set => SetValue(IconSizeProperty, value);
}
public static readonly DependencyProperty IconSizeProperty = DependencyProperty.Register(
nameof(IconSize),
typeof(double),
typeof(HorizontalIconText),
new PropertyMetadata(14d)
);
public double Spacing
{
get => (double)GetValue(SpacingProperty);
set => SetValue(SpacingProperty, value);
}
public static readonly DependencyProperty SpacingProperty = DependencyProperty.Register(
nameof(Spacing),
typeof(double),
typeof(HorizontalIconText),
new PropertyMetadata(4d)
);
private static void OnOnIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is HorizontalIconText view)
{
view.ShowIcon = view.Icon.IsNotBlank();
}
}
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.Property == ShowSpaceProperty)
{
return;
}
ShowSpace = ShowIcon && Text.IsNotBlank();
}
}
}
@@ -72,7 +72,7 @@ internal static class ViewLifecycle
if (ReferenceEquals(previous, next)) return;
view.SetValue(LoadedViewModelProperty, next);
previous?.OnUnloaded();
next?.OnLoaded();
next?.NotifyLoaded();
}
private static void OnUnloaded(object sender, RoutedEventArgs e)
@@ -5,6 +5,20 @@ namespace Store.Management.Framework.Controls;
public abstract class ViewModelBase : BindableBase
{
private bool hasLoaded;
internal void NotifyLoaded()
{
if (!hasLoaded)
{
hasLoaded = true;
OnLoadedOnce();
}
OnLoaded();
}
/// <summary>当前实例首次加载时调用,先于 OnLoaded。</summary>
protected virtual void OnLoadedOnce() { }
protected internal virtual void OnLoaded() { }
protected internal virtual void OnUnloaded() { }
protected internal virtual void OnActivated() { }
@@ -1,8 +1,12 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:f="clr-namespace:Store.Management.Framework.Controls"
xmlns:wpf="MAX.WPF">
xmlns:hc="https://handyorg.github.io/handycontrol"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wpf="MAX.WPF"
mc:Ignorable="d">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Fonts/FontGeometry.xaml" />
<ResourceDictionary Source="pack://application:,,,/MAX.Common.WPF;component/Resources/Generic.xaml" />
@@ -37,6 +41,180 @@
<Style BasedOn="{StaticResource WindowBase}" TargetType="f:WindowBase" />
<Style BasedOn="{StaticResource DialogWindowStyle}" TargetType="f:DialogWindow" />
<!--<Style x:Key="HorizontalSpacingPanel" TargetType="hc:UniformSpacingPanel">
<Setter Property="Orientation" Value="Horizontal" />
<Setter Property="HorizontalSpacing" Value="2" />
<Setter Property="ItemVerticalAlignment" Value="Center" />
</Style>-->
<!--<Style x:Key="HorizontalSpacingPanel2" TargetType="hc:UniformSpacingPanel">
<Setter Property="Orientation" Value="Horizontal" />
<Setter Property="HorizontalSpacing" Value="4" />
<Setter Property="ItemVerticalAlignment" Value="Center" />
</Style>
<Style x:Key="VerticalSpacingPanel" TargetType="hc:UniformSpacingPanel">
<Setter Property="Orientation" Value="Vertical" />
<Setter Property="VerticalSpacing" Value="2" />
</Style>
<Style x:Key="VerticalSpacingPanel2" TargetType="hc:UniformSpacingPanel">
<Setter Property="Orientation" Value="Vertical" />
<Setter Property="VerticalSpacing" Value="4" />
</Style>-->
<Style x:Key="HorizontalSpacingPanel" TargetType="wpf:SpacingStackPanel">
<Setter Property="Orientation" Value="Horizontal" />
<Setter Property="HorizontalSpacing" Value="2" />
<Setter Property="ItemVerticalAlignment" Value="Center" />
</Style>
<Style x:Key="HorizontalSpacingPanel4" TargetType="wpf:SpacingStackPanel">
<Setter Property="Orientation" Value="Horizontal" />
<Setter Property="HorizontalSpacing" Value="4" />
<Setter Property="ItemVerticalAlignment" Value="Center" />
</Style>
<Style x:Key="HorizontalSpacingPanel8" TargetType="wpf:SpacingStackPanel">
<Setter Property="Orientation" Value="Horizontal" />
<Setter Property="HorizontalSpacing" Value="8" />
<Setter Property="ItemVerticalAlignment" Value="Center" />
</Style>
<Style x:Key="VerticalSpacingPanel" TargetType="wpf:SpacingStackPanel">
<Setter Property="Orientation" Value="Vertical" />
<Setter Property="VerticalSpacing" Value="2" />
</Style>
<Style x:Key="VerticalSpacingPanel4" TargetType="wpf:SpacingStackPanel">
<Setter Property="Orientation" Value="Vertical" />
<Setter Property="VerticalSpacing" Value="4" />
</Style>
<Style x:Key="VerticalSpacingPanel8" TargetType="wpf:SpacingStackPanel">
<Setter Property="Orientation" Value="Vertical" />
<Setter Property="VerticalSpacing" Value="8" />
</Style>
<Style
x:Key="HorizontalIconText"
BasedOn="{StaticResource BaseStyle}"
TargetType="f:HorizontalIconText">
<Setter Property="Spacing" Value="4" />
<Setter Property="Focusable" Value="False" />
<Setter Property="IconSize" Value="16" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="f:HorizontalIconText">
<Border>
<DockPanel>
<TextBlock
FontSize="{TemplateBinding IconSize}"
Style="{StaticResource TextBlockIcon}"
Text="{TemplateBinding Icon}"
Visibility="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ShowIcon, Converter={StaticResource Boolean2VisibilityConverter}}" />
<Border Width="{TemplateBinding Spacing}" Visibility="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ShowSpace, Converter={StaticResource Boolean2VisibilityConverter}}" />
<TextBlock
VerticalAlignment="Center"
Text="{TemplateBinding Text}"
TextTrimming="CharacterEllipsis" />
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style BasedOn="{StaticResource HorizontalIconText}" TargetType="f:HorizontalIconText" />
<Style x:Key="Dialog" TargetType="UserControl">
<Setter Property="Padding" Value="0" />
<Setter Property="Focusable" Value="True" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Background" Value="White" />
</Style>
<Style
x:Key="DialogButtonStyle"
BasedOn="{StaticResource ButtonDefault}"
TargetType="Button">
<Setter Property="MinWidth" Value="70" />
<Setter Property="Height" Value="26" />
</Style>
<Style
x:Key="DialogPrimaryButtonStyle"
BasedOn="{StaticResource ButtonPrimary}"
TargetType="Button">
<Setter Property="MinWidth" Value="70" />
<Setter Property="Height" Value="26" />
</Style>
<Style
x:Key="ConfirmDialog"
BasedOn="{StaticResource Dialog}"
TargetType="UserControl">
<Setter Property="Background" Value="White" />
<Setter Property="Padding" Value="10" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="UserControl">
<Border
d:DataContext="{d:DesignInstance Type=f:ConfirmDialogViewModel}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Border Padding="{TemplateBinding Padding}">
<ContentPresenter />
</Border>
<Border
Grid.Row="1"
Padding="5,8"
BorderBrush="{StaticResource BorderBrush}"
BorderThickness="0,1,0,0">
<Grid>
<Border Padding="2,0">
<f:HorizontalIconText
d:Text="错误信息"
Foreground="{StaticResource DangerBrush}"
Icon="{StaticResource txt-warning}"
Text="{Binding ErrorMsg}"
Visibility="{Binding ErrorMsg, Converter={StaticResource String2VisibilityConverter}}" />
</Border>
<wpf:SpacingStackPanel HorizontalAlignment="Right" Style="{StaticResource HorizontalSpacingPanel4}">
<Button Command="{Binding ConfirmCommand}" Style="{StaticResource DialogPrimaryButtonStyle}">
<TextBlock Text="确认" />
</Button>
<Button
HorizontalAlignment="Right"
Command="{Binding CancelCommand}"
Style="{StaticResource DialogButtonStyle}">
<TextBlock Text="取消" />
</Button>
</wpf:SpacingStackPanel>
</Grid>
</Border>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style
x:Key="VerticalAlignment"
BasedOn="{StaticResource TitleContentBaseStyle}"
@@ -10,6 +10,8 @@ public interface IUserService
Task<PageResult<UserInfo>> SearchAsync(UserSearchRequest request, CancellationToken cancellationToken = default);
Task<UserInfo> CreateAsync(UserCreateRequest request, CancellationToken cancellationToken = default);
Task<UserInfo> UpdateAsync(UserUpdateRequest request, CancellationToken cancellationToken = default);
Task<UserInfo> UpdateBillingAsync(UserBillingUpdateRequest request, CancellationToken cancellationToken = default);
Task ChangePasswordAsync(ChangePasswordRequest request, CancellationToken cancellationToken = default);
Task DeleteAsync(int id, CancellationToken cancellationToken = default);
}
@@ -24,6 +26,12 @@ internal sealed class UserService(StoreApiClient client) : IUserService, ISingle
public Task<UserInfo> UpdateAsync(UserUpdateRequest request, CancellationToken cancellationToken = default)
=> client.Users.UpdateAsync(request, cancellationToken);
public Task<UserInfo> UpdateBillingAsync(UserBillingUpdateRequest request, CancellationToken cancellationToken = default)
=> client.Users.UpdateBillingAsync(request, cancellationToken);
public Task ChangePasswordAsync(ChangePasswordRequest request, CancellationToken cancellationToken = default)
=> client.Users.ChangePasswordAsync(request, cancellationToken);
public Task DeleteAsync(int id, CancellationToken cancellationToken = default)
=> client.Users.DeleteAsync(id, cancellationToken);
}