Forráskód Böngészése

完成注册开发

宝臣 王 3 hónapja
szülő
commit
622a600be4

+ 1 - 1
UniformMaterialManagementSystem/App.xaml

@@ -2,7 +2,7 @@
     x:Class="UniformMaterialManagementSystem.App"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-    StartupUri="Views/LoginPage.xaml">
+    StartupUri="Views/LoginAndRegisterWindow.xaml">
     <Application.Resources>
         <ResourceDictionary>
             <FontFamily x:Key="FluentSystemIconsFilled">pack://application:,,,/Resources/Fonts/FluentSystemIcons-Filled.ttf#FluentSystemIcons-Filled</FontFamily>

+ 7 - 2
UniformMaterialManagementSystem/App.xaml.cs

@@ -9,6 +9,7 @@ using UniformMaterialManagementSystem.Models;
 using UniformMaterialManagementSystem.Services;
 using UniformMaterialManagementSystem.ViewModels;
 using UniformMaterialManagementSystem.Views;
+using UniformMaterialManagementSystem.Views.LoginAndRegister;
 
 namespace UniformMaterialManagementSystem
 {
@@ -46,7 +47,9 @@ namespace UniformMaterialManagementSystem
 
             // View 注册
             services.AddSingleton<MainWindow>();
-            services.AddSingleton<LoginPage>();
+            services.AddTransient<LoginPage>();
+            services.AddTransient<RegisterPage>();
+            services.AddSingleton<LoginAndRegisterWindow>();
             services.AddKeyedTransient<UserControl, HomePage>("HomePage");
             services.AddKeyedTransient<UserControl, MenuPage>("MenuPage");
             services.AddKeyedTransient<UserControl, SupervisionUnitPage>("SupervisionUnitPage");
@@ -69,7 +72,9 @@ services.AddKeyedTransient<UserControl, InspectionOrganizationPage>("InspectionO
 
             // ViewModel 注册
             services.AddSingleton<MainWindowViewModel>();
-            services.AddSingleton<LoginPageViewModel>();
+            services.AddSingleton<LoginAndRegisterViewModel>();
+            services.AddTransient<LoginPageViewModel>();
+            services.AddTransient<RegisterPageViewModel>();
             services.AddTransient<HomePageViewModel>();
             services.AddTransient<MenuPageViewModel>();
             services.AddTransient<SupervisionUnitPageViewModel>();

+ 275 - 0
UniformMaterialManagementSystem/Custom/FilterCombobox.cs

@@ -0,0 +1,275 @@
+using System.Collections;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Data;
+using System.Windows.Input;
+
+namespace UniformMaterialManagementSystem.Custom
+{
+    public class FilterableComboBox : ComboBox
+    {
+        public bool OnlyValuesInList
+        {
+            get => (bool)GetValue(OnlyValuesInListProperty);
+            set => SetValue(OnlyValuesInListProperty, value);
+        }
+
+        public static readonly DependencyProperty OnlyValuesInListProperty =
+            DependencyProperty.Register(nameof(OnlyValuesInList), typeof(bool), typeof(FilterableComboBox));
+
+        public object EffectivelySelectedItem
+        {
+            get => (bool)GetValue(EffectivelySelectedItemProperty);
+            set => SetValue(EffectivelySelectedItemProperty, value);
+        }
+        public static readonly DependencyProperty EffectivelySelectedItemProperty =
+            DependencyProperty.Register(nameof(EffectivelySelectedItem), typeof(object), typeof(FilterableComboBox));
+
+        private string _currentFilter = string.Empty;
+        private bool _textBoxFreezed;
+
+        protected TextBox? EditableTextBox => GetTemplateChild("PART_EditableTextBox") as TextBox;
+        private readonly UserChange<bool> _isDropDownOpenUc;
+
+        public event Action<FilterableComboBox, object> SelectionEffectivelyChanged;
+
+        public FilterableComboBox()
+        {
+            _isDropDownOpenUc = new UserChange<bool>(v => IsDropDownOpen = v);
+            DropDownOpened += FilteredComboBox_DropDownOpened;
+
+            IsEditable = true;
+            IsTextSearchEnabled = true;
+            StaysOpenOnEdit = true;
+            IsReadOnly = false;
+
+            Loaded += (_, _) =>
+            {
+                if (EditableTextBox != null)
+                    new TextBoxBaseUserChangeTracker(EditableTextBox).UserTextChanged += FilteredComboBox_UserTextChange;
+            };
+
+            SelectionChanged += (_, _) => _shouldTriggerSelectedItemChanged = true;
+
+            SelectionEffectivelyChanged += (_, o) => EffectivelySelectedItem = o;
+        }
+
+        protected override void OnPreviewKeyDown(KeyEventArgs e)
+        {
+            base.OnPreviewKeyDown(e);
+            if (e.Key == Key.Down && !IsDropDownOpen)
+            {
+                IsDropDownOpen = true;
+                e.Handled = true;
+            }
+            else if (e.Key == Key.Escape)
+            {
+                ClearFilter();
+                Text = "";
+                IsDropDownOpen = true;
+            }
+            else if (e.Key == Key.Enter || e.Key == Key.Tab)
+            {
+                CheckSelectedItem();
+                TriggerSelectedItemChanged();
+            }
+        }
+
+        protected override void OnPreviewLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
+        {
+            base.OnPreviewLostKeyboardFocus(e);
+            CheckSelectedItem();
+
+            if ((Equals(e.OldFocus, this) || Equals(e.OldFocus, EditableTextBox)) && !Equals(e.NewFocus, this) && !Equals(e.NewFocus, EditableTextBox))
+                TriggerSelectedItemChanged();
+        }
+
+        private void CheckSelectedItem()
+        {
+            if (OnlyValuesInList)
+                Text = SelectedItem?.ToString() ?? "";
+        }
+
+        private bool _shouldTriggerSelectedItemChanged;
+        private void TriggerSelectedItemChanged()
+        {
+            if (!_shouldTriggerSelectedItemChanged) return;
+
+            SelectionEffectivelyChanged(this, SelectedItem);
+            _shouldTriggerSelectedItemChanged = false;
+        }
+
+        public void ClearFilter()
+        {
+            if (string.IsNullOrEmpty(_currentFilter)) return;
+            _currentFilter = "";
+            CollectionViewSource.GetDefaultView(ItemsSource).Refresh();
+        }
+
+        private void FilteredComboBox_DropDownOpened(object? sender, EventArgs e)
+        {
+            if (_isDropDownOpenUc.IsUserChange)
+                ClearFilter();
+        }
+
+        private void FilteredComboBox_UserTextChange(object? sender, EventArgs e)
+        {
+            if (_textBoxFreezed || EditableTextBox == null) return;
+            var tb = EditableTextBox;
+            _currentFilter = tb.SelectionStart + tb.SelectionLength == tb.Text.Length
+                ? tb.Text[..tb.SelectionStart].ToLower()
+                : tb.Text.ToLower();
+
+            RefreshFilter();
+        }
+
+        protected override void OnItemsSourceChanged(IEnumerable? oldValue, IEnumerable? newValue)
+        {
+            if (newValue != null)
+            {
+                var view = CollectionViewSource.GetDefaultView(newValue);
+                view.Filter += FilterItem;
+            }
+
+            if (oldValue != null)
+            {
+                var view = CollectionViewSource.GetDefaultView(oldValue);
+                if (view != null) view.Filter -= FilterItem;
+            }
+
+            base.OnItemsSourceChanged(oldValue, newValue);
+        }
+
+        private void RefreshFilter()
+        {
+            if (ItemsSource == null) return;
+
+            var view = CollectionViewSource.GetDefaultView(ItemsSource);
+            FreezTextBoxState(() =>
+            {
+                var isDropDownOpen = IsDropDownOpen;
+                _isDropDownOpenUc.Set(false);
+                view.Refresh();
+
+                if (!string.IsNullOrEmpty(_currentFilter) || isDropDownOpen)
+                    _isDropDownOpenUc.Set(true);
+
+                if (SelectedItem != null) return;
+
+                foreach (var itm in ItemsSource)
+                    if (itm.ToString() == Text)
+                    {
+                        SelectedItem = itm;
+                        break;
+                    }
+            });
+        }
+
+        private void FreezTextBoxState(Action action)
+        {
+            _textBoxFreezed = true;
+            var tb = EditableTextBox;
+            var text = Text;
+            if (tb != null)
+            {
+                var selStart = tb.SelectionStart;
+                var selLen = tb.SelectionLength;
+                action();
+                Text = text;
+                tb.SelectionStart = selStart;
+                tb.SelectionLength = selLen;
+            }
+
+            _textBoxFreezed = false;
+        }
+
+        private bool FilterItem(object? value)
+        {
+            if (value == null) return false;
+            if (_currentFilter.Length == 0) return true;
+
+            return value.ToString()!.ToLower().Contains(_currentFilter);
+        }
+
+        private class TextBoxBaseUserChangeTracker
+        {
+            private bool IsTextInput { get; set; }
+
+            private TextBoxBase TextBoxBase { get; }
+            private readonly List<Key> _pressedKeys = new();
+            public event EventHandler? UserTextChanged;
+
+            public TextBoxBaseUserChangeTracker(TextBoxBase textBoxBase)
+            {
+                TextBoxBase = textBoxBase;
+                var lastText = TextBoxBase.ToString();
+
+                textBoxBase.PreviewTextInput += (_, _) =>
+                {
+                    IsTextInput = true;
+                };
+
+                textBoxBase.TextChanged += (_, e) =>
+                {
+                    var isUserChange = _pressedKeys.Count > 0 || IsTextInput || lastText == TextBoxBase.ToString();
+                    IsTextInput = false;
+                    lastText = TextBoxBase.ToString();
+                    if (isUserChange)
+                        UserTextChanged?.Invoke(this, e);
+                };
+
+                textBoxBase.PreviewKeyDown += (_, e) =>
+                {
+                    switch (e.Key)
+                    {
+                        case Key.Back:
+                        case Key.Space:
+                            if (!_pressedKeys.Contains(e.Key))
+                                _pressedKeys.Add(e.Key);
+                            break;
+                    }
+
+                    if (e.Key != Key.Back) return;
+                    if (textBoxBase is not TextBox { SelectionStart: > 0, SelectionLength: > 0 } textBox ||
+                        (textBox.SelectionStart + textBox.SelectionLength) != textBox.Text.Length) return;
+
+                    textBox.SelectionStart--;
+                    textBox.SelectionLength++;
+                    e.Handled = true;
+                    UserTextChanged?.Invoke(this, e);
+                };
+
+                textBoxBase.PreviewKeyUp += (_, e) =>
+                {
+                    if (_pressedKeys.Contains(e.Key))
+                        _pressedKeys.Remove(e.Key);
+                };
+
+                textBoxBase.LostFocus += (_, _) =>
+                {
+                    _pressedKeys.Clear();
+                    IsTextInput = false;
+                };
+            }
+        }
+
+        private class UserChange<T>(Action<T> action)
+        {
+            public bool IsUserChange { get; private set; } = true;
+
+            public void Set(T val)
+            {
+                try
+                {
+                    IsUserChange = false;
+                    action(val);
+                }
+                finally
+                {
+                    IsUserChange = true;
+                }
+            }
+        }
+    }
+}

+ 5 - 0
UniformMaterialManagementSystem/Entities/Company.cs

@@ -37,5 +37,10 @@ namespace UniformMaterialManagementSystem.Entities
         
         [NotMapped]
         public bool IsNewRow { get; set; } = true;
+
+        public override string ToString()
+        {
+            return Name;
+        }
     }
 }

+ 6 - 3
UniformMaterialManagementSystem/Entities/SupervisionUnit.cs

@@ -8,7 +8,7 @@ namespace UniformMaterialManagementSystem.Entities
     public class SupervisionUnit
     {
         [Key]
-        public Guid Guid { get; set; }=Guid.NewGuid();
+        public Guid Guid { get; set; } = Guid.NewGuid();
 
         [StringLength(50)]
         public string Name { get; set; } = null!;
@@ -19,8 +19,11 @@ namespace UniformMaterialManagementSystem.Entities
         [StringLength(100)]
         public string? Note { get; set; }
 
-        public bool IsEnabled {  get; set; }
-
+        public bool IsEnabled { get; set; }
 
+        public override string ToString()
+        {
+            return Name;
+        }
     }
 }

+ 250 - 19
UniformMaterialManagementSystem/Resources/ControlStyle.xaml

@@ -14,12 +14,245 @@
             </Border>
 
             <TextBlock
+                HorizontalAlignment="Right"
                 Background="Transparent"
                 Foreground="Red"
                 Text="{Binding /ErrorContent}" />
         </StackPanel>
     </ControlTemplate>
 
+    <Style x:Key="ScrollBarThumb" TargetType="{x:Type Thumb}">
+        <Setter Property="OverridesDefaultStyle" Value="true" />
+        <Setter Property="IsTabStop" Value="false" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Thumb}">
+                    <Grid>
+                        <Rectangle
+                            Fill="#0c9ea1"
+                            RadiusX="3"
+                            RadiusY="3" />
+                    </Grid>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+
+    <Style x:Key="HorizontalScrollBarPageButton" TargetType="{x:Type RepeatButton}">
+        <Setter Property="OverridesDefaultStyle" Value="true" />
+        <Setter Property="Background" Value="Transparent" />
+        <Setter Property="Focusable" Value="false" />
+        <Setter Property="IsTabStop" Value="false" />
+        <Setter Property="Opacity" Value="0" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type RepeatButton}">
+                    <Rectangle
+                        Width="{TemplateBinding Width}"
+                        Height="{TemplateBinding Height}"
+                        Fill="{TemplateBinding Background}" />
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+
+    <Style x:Key="VerticalScrollBarPageButton" TargetType="{x:Type RepeatButton}">
+        <Setter Property="OverridesDefaultStyle" Value="true" />
+        <Setter Property="Background" Value="Transparent" />
+        <Setter Property="Focusable" Value="false" />
+        <Setter Property="IsTabStop" Value="false" />
+        <Setter Property="Opacity" Value="0" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type RepeatButton}">
+                    <Rectangle
+                        Width="{TemplateBinding Width}"
+                        Height="{TemplateBinding Height}"
+                        Fill="{TemplateBinding Background}" />
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+
+    <Style x:Key="ForScrollbar" TargetType="{x:Type ScrollBar}">
+        <Setter Property="Stylus.IsPressAndHoldEnabled" Value="false" />
+        <Setter Property="Stylus.IsFlicksEnabled" Value="false" />
+        <Setter Property="Background" Value="Transparent" />
+        <Setter Property="Margin" Value="0,1,1,6" />
+        <Setter Property="Width" Value="5" />
+        <Setter Property="MinWidth" Value="5" />
+        <Setter Property="Opacity" Value="0" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type ScrollBar}">
+                    <Grid x:Name="Bg" SnapsToDevicePixels="true">
+                        <Track
+                            x:Name="PART_Track"
+                            IsDirectionReversed="true"
+                            IsEnabled="{TemplateBinding IsMouseOver}">
+                            <Track.DecreaseRepeatButton>
+                                <RepeatButton Command="{x:Static ScrollBar.PageUpCommand}" Style="{StaticResource VerticalScrollBarPageButton}" />
+                            </Track.DecreaseRepeatButton>
+                            <Track.IncreaseRepeatButton>
+                                <RepeatButton Command="{x:Static ScrollBar.PageDownCommand}" Style="{StaticResource VerticalScrollBarPageButton}" />
+                            </Track.IncreaseRepeatButton>
+                            <Track.Thumb>
+                                <Thumb Style="{StaticResource ScrollBarThumb}" />
+                            </Track.Thumb>
+                        </Track>
+                    </Grid>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+        <Style.Triggers>
+            <Trigger Property="Orientation" Value="Horizontal">
+                <Setter Property="Background" Value="Transparent" />
+                <Setter Property="Margin" Value="1,0,6,1" />
+                <Setter Property="Height" Value="5" />
+                <Setter Property="MinHeight" Value="5" />
+                <Setter Property="Width" Value="Auto" />
+                <Setter Property="Opacity" Value="0" />
+                <Setter Property="Template">
+                    <Setter.Value>
+                        <ControlTemplate TargetType="{x:Type ScrollBar}">
+                            <Grid x:Name="Bg" SnapsToDevicePixels="true">
+                                <Track x:Name="PART_Track" IsEnabled="{TemplateBinding IsMouseOver}">
+                                    <Track.DecreaseRepeatButton>
+                                        <RepeatButton Command="{x:Static ScrollBar.PageLeftCommand}" Style="{StaticResource HorizontalScrollBarPageButton}" />
+                                    </Track.DecreaseRepeatButton>
+                                    <Track.IncreaseRepeatButton>
+                                        <RepeatButton Command="{x:Static ScrollBar.PageRightCommand}" Style="{StaticResource HorizontalScrollBarPageButton}" />
+                                    </Track.IncreaseRepeatButton>
+                                    <Track.Thumb>
+                                        <Thumb Style="{StaticResource ScrollBarThumb}" />
+                                    </Track.Thumb>
+                                </Track>
+                            </Grid>
+                        </ControlTemplate>
+                    </Setter.Value>
+                </Setter>
+            </Trigger>
+        </Style.Triggers>
+    </Style>
+
+    <Style x:Key="ForScrollViewer" TargetType="{x:Type ScrollViewer}">
+        <Setter Property="BorderBrush" Value="LightGray" />
+        <Setter Property="BorderThickness" Value="0" />
+        <Setter Property="HorizontalContentAlignment" Value="Left" />
+        <Setter Property="HorizontalScrollBarVisibility" Value="Auto" />
+        <Setter Property="VerticalContentAlignment" Value="Top" />
+        <Setter Property="VerticalScrollBarVisibility" Value="Auto" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type ScrollViewer}">
+                    <Border
+                        BorderBrush="{TemplateBinding BorderBrush}"
+                        BorderThickness="{TemplateBinding BorderThickness}"
+                        SnapsToDevicePixels="True">
+                        <Grid Background="{TemplateBinding Background}">
+                            <ScrollContentPresenter
+                                Margin="{TemplateBinding Padding}"
+                                ContentTemplate="{TemplateBinding ContentTemplate}"
+                                Cursor="{TemplateBinding Cursor}" />
+                            <ScrollBar
+                                x:Name="PART_VerticalScrollBar"
+                                HorizontalAlignment="Right"
+                                Maximum="{TemplateBinding ScrollableHeight}"
+                                Orientation="Vertical"
+                                Style="{StaticResource ForScrollbar}"
+                                ViewportSize="{TemplateBinding ViewportHeight}"
+                                Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
+                                Value="{TemplateBinding VerticalOffset}" />
+                            <ScrollBar
+                                x:Name="PART_HorizontalScrollBar"
+                                VerticalAlignment="Bottom"
+                                Maximum="{TemplateBinding ScrollableWidth}"
+                                Orientation="Horizontal"
+                                Style="{StaticResource ForScrollbar}"
+                                ViewportSize="{TemplateBinding ViewportWidth}"
+                                Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
+                                Value="{TemplateBinding HorizontalOffset}" />
+                        </Grid>
+                    </Border>
+                    <ControlTemplate.Triggers>
+                        <EventTrigger RoutedEvent="ScrollChanged">
+                            <BeginStoryboard>
+                                <Storyboard>
+                                    <DoubleAnimation
+                                        Storyboard.TargetName="PART_VerticalScrollBar"
+                                        Storyboard.TargetProperty="Opacity"
+                                        To="1"
+                                        Duration="0:0:1" />
+                                    <DoubleAnimation
+                                        BeginTime="0:0:1"
+                                        Storyboard.TargetName="PART_VerticalScrollBar"
+                                        Storyboard.TargetProperty="Opacity"
+                                        To="0"
+                                        Duration="0:0:1" />
+                                    <DoubleAnimation
+                                        Storyboard.TargetName="PART_HorizontalScrollBar"
+                                        Storyboard.TargetProperty="Opacity"
+                                        To="1"
+                                        Duration="0:0:1" />
+                                    <DoubleAnimation
+                                        BeginTime="0:0:1"
+                                        Storyboard.TargetName="PART_HorizontalScrollBar"
+                                        Storyboard.TargetProperty="Opacity"
+                                        To="0"
+                                        Duration="0:0:1" />
+                                </Storyboard>
+                            </BeginStoryboard>
+                        </EventTrigger>
+                        <EventTrigger RoutedEvent="MouseEnter" SourceName="PART_VerticalScrollBar">
+                            <BeginStoryboard>
+                                <Storyboard>
+                                    <DoubleAnimation
+                                        Storyboard.TargetName="PART_VerticalScrollBar"
+                                        Storyboard.TargetProperty="Opacity"
+                                        To="1"
+                                        Duration="0:0:1" />
+                                </Storyboard>
+                            </BeginStoryboard>
+                        </EventTrigger>
+                        <EventTrigger RoutedEvent="MouseLeave" SourceName="PART_VerticalScrollBar">
+                            <BeginStoryboard>
+                                <Storyboard>
+                                    <DoubleAnimation
+                                        Storyboard.TargetName="PART_VerticalScrollBar"
+                                        Storyboard.TargetProperty="Opacity"
+                                        To="0"
+                                        Duration="0:0:1" />
+                                </Storyboard>
+                            </BeginStoryboard>
+                        </EventTrigger>
+                        <EventTrigger RoutedEvent="MouseEnter" SourceName="PART_HorizontalScrollBar">
+                            <BeginStoryboard>
+                                <Storyboard>
+                                    <DoubleAnimation
+                                        Storyboard.TargetName="PART_HorizontalScrollBar"
+                                        Storyboard.TargetProperty="Opacity"
+                                        To="1"
+                                        Duration="0:0:1" />
+                                </Storyboard>
+                            </BeginStoryboard>
+                        </EventTrigger>
+                        <EventTrigger RoutedEvent="MouseLeave" SourceName="PART_HorizontalScrollBar">
+                            <BeginStoryboard>
+                                <Storyboard>
+                                    <DoubleAnimation
+                                        Storyboard.TargetName="PART_HorizontalScrollBar"
+                                        Storyboard.TargetProperty="Opacity"
+                                        To="0"
+                                        Duration="0:0:1" />
+                                </Storyboard>
+                            </BeginStoryboard>
+                        </EventTrigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+
     <Style x:Key="ExpandCollapseToggleStyle" TargetType="{x:Type ToggleButton}">
         <Setter Property="Focusable" Value="False" />
         <Setter Property="Width" Value="20" />
@@ -159,17 +392,17 @@
             <Label
                 x:Name="downArrow"
                 Grid.Column="1"
-                Width="28"
-                Height="28"
                 Margin="6,0,6,0"
+                HorizontalContentAlignment="Center"
+                VerticalContentAlignment="Center"
                 Content="{x:Static utils:RegularFontUtil.Chevron_Down_48}"
                 FontFamily="{DynamicResource FluentSystemIconsRegular}" />
             <Label
                 x:Name="upArrow"
                 Grid.Column="1"
-                Width="28"
-                Height="28"
                 Margin="6,0,6,0"
+                HorizontalContentAlignment="Center"
+                VerticalContentAlignment="Center"
                 Content="{x:Static utils:RegularFontUtil.Chevron_Up_48}"
                 FontFamily="{DynamicResource FluentSystemIconsRegular}"
                 Visibility="Collapsed" />
@@ -230,15 +463,14 @@
                                 IsHitTestVisible="False" />
                             <TextBox
                                 x:Name="PART_EditableTextBox"
-                                Margin="3,3,23,3"
-                                HorizontalAlignment="Left"
-                                VerticalAlignment="Bottom"
+                                HorizontalAlignment="Center"
+                                VerticalAlignment="Center"
                                 Background="Transparent"
                                 Focusable="True"
                                 IsReadOnly="{TemplateBinding IsReadOnly}"
                                 Style="{x:Null}"
                                 Template="{StaticResource ComboBoxTextBox}"
-                                Visibility="Hidden" />
+                                Visibility="Visible" />
                             <Popup
                                 x:Name="Popup"
                                 MaxHeight="{TemplateBinding MaxDropDownHeight}"
@@ -258,15 +490,17 @@
                                     <Border
                                         x:Name="DropDownBorder"
                                         BorderBrush="#E4E9F2"
-                                        BorderThickness="1,1,1,1">
+                                        BorderThickness="1,1,1,1"
+                                        CornerRadius="5">
                                         <Border.Background>
                                             <SolidColorBrush Color="White" />
                                         </Border.Background>
                                     </Border>
                                     <ScrollViewer
-                                        Margin="1,5"
+                                        Margin="1,3"
                                         Padding="0"
-                                        SnapsToDevicePixels="True">
+                                        SnapsToDevicePixels="True"
+                                        Style="{StaticResource ForScrollViewer}">
                                         <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
                                     </ScrollViewer>
 
@@ -304,21 +538,19 @@
                 <Style BasedOn="{StaticResource {x:Type ComboBoxItem}}" TargetType="ComboBoxItem">
                     <Setter Property="Foreground" Value="#3E434D" />
                     <Setter Property="Height" Value="36" />
+                    <Setter Property="VerticalContentAlignment" Value="Center" />
+                    <Setter Property="HorizontalContentAlignment" Value="Center" />
                     <Setter Property="Template">
                         <Setter.Value>
                             <ControlTemplate TargetType="ComboBoxItem">
                                 <Border
                                     x:Name="Border"
-                                    Padding="6,10,6,0"
-                                    VerticalAlignment="Center"
+                                    Height="{TemplateBinding Height}"
                                     Background="Transparent"
                                     SnapsToDevicePixels="true">
                                     <ContentPresenter
-                                        Width="{TemplateBinding Width}"
-                                        Height="{TemplateBinding Height}"
-                                        Margin="{TemplateBinding Margin}"
-                                        HorizontalAlignment="Center"
-                                        VerticalAlignment="{TemplateBinding VerticalAlignment}"
+                                        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
+                                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                         Content="{TemplateBinding Content}"
                                         ContentTemplate="{TemplateBinding ContentTemplate}" />
                                 </Border>
@@ -338,5 +570,4 @@
         </Setter>
     </Style>
 
-
 </ResourceDictionary>

+ 0 - 2
UniformMaterialManagementSystem/Resources/Icons.xaml

@@ -11,8 +11,6 @@
                         Name="svg_1"
                         Width="327"
                         Height="301"
-                        Fill="#FF0D2505"
-                        Stroke="#FF395934"
                         StrokeThickness="1.51" />
                     <Canvas Name="svg_11">
                         <Canvas Name="svg_12">

+ 22 - 0
UniformMaterialManagementSystem/ViewModels/LoginAndRegisterViewModel.cs

@@ -0,0 +1,22 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+
+using UniformMaterialManagementSystem.Views.LoginAndRegister;
+
+namespace UniformMaterialManagementSystem.ViewModels
+{
+    public partial class LoginAndRegisterViewModel : ObservableObject
+    {
+        [ObservableProperty]
+        private object? _currentView;
+
+        public LoginAndRegisterViewModel()
+        {
+            CurrentView = App.Current.Services.GetService(typeof(LoginPage));
+        }
+
+        public void SwitchPage(object? view)
+        {
+            CurrentView = view;
+        }
+    }
+}

+ 9 - 9
UniformMaterialManagementSystem/ViewModels/LoginPageViewModel.cs

@@ -5,12 +5,12 @@ using System.ComponentModel.DataAnnotations;
 using System.Windows;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.DependencyInjection;
-using UniformMaterialManagementSystem.Data;
 using UniformMaterialManagementSystem.Entities;
 using UniformMaterialManagementSystem.Models;
 using UniformMaterialManagementSystem.Services;
 using UniformMaterialManagementSystem.Utils;
 using UniformMaterialManagementSystem.Views;
+using UniformMaterialManagementSystem.Views.LoginAndRegister;
 using static System.Text.RegularExpressions.Regex;
 
 namespace UniformMaterialManagementSystem.ViewModels
@@ -40,14 +40,12 @@ namespace UniformMaterialManagementSystem.ViewModels
 
         private static User? _user;
 
-        public LoginPageViewModel(IDataBaseService<User>? service, SqliteContext context)
+        public LoginPageViewModel(IDataBaseService<User>? service)
         {
-            context.Database.EnsureCreated();
-
             _service = service;
-            
-            var currYear = DateTime.Now.Year;
-            Years= [currYear, currYear + 1];
+
+            WorkYear = DateTime.Now.Year;
+            Years = [WorkYear, WorkYear + 1];
         }
 
         [RelayCommand]
@@ -71,9 +69,11 @@ namespace UniformMaterialManagementSystem.ViewModels
         }
 
         [RelayCommand]
-        private void Cancel(Window loginWindow)
+        private void Register()
         {
-            loginWindow.Close();
+            var model = App.Current.Services.GetService<LoginAndRegisterViewModel>();
+            var registerPage = App.Current.Services.GetService<RegisterPage>();
+            model?.SwitchPage(registerPage);
         }
 
         public static ValidationResult? ValidateUserName(string userName, ValidationContext context)

+ 149 - 0
UniformMaterialManagementSystem/ViewModels/RegisterPageViewModel.cs

@@ -0,0 +1,149 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+
+using System.ComponentModel.DataAnnotations;
+using System.Windows;
+using Microsoft.Extensions.DependencyInjection;
+using UniformMaterialManagementSystem.Data;
+using UniformMaterialManagementSystem.Entities;
+using UniformMaterialManagementSystem.Services;
+using UniformMaterialManagementSystem.Views.LoginAndRegister;
+using static System.Text.RegularExpressions.Regex;
+using UniformMaterialManagementSystem.Utils;
+
+namespace UniformMaterialManagementSystem.ViewModels
+{
+    public partial class RegisterPageViewModel : ObservableValidator
+    {
+        private readonly IDictionary<string, Role> _roles = new Dictionary<string, Role>();
+
+        [ObservableProperty]
+        private IDictionary<string, string> _unitTypes = new Dictionary<string, string>()
+        {
+            { "SupervisionUser", "质量监督站" },
+            { "ProductCompanyUser", "成品生产企业" },
+            { "MaterialCompanyUser", "成品生产企业" }
+        };
+
+        [ObservableProperty]
+        private string _selectedUnitType = string.Empty;
+
+        [ObservableProperty]
+        private ICollection<SupervisionUnit> _units = [];
+
+        [ObservableProperty]
+        private SupervisionUnit _selectedUnit = null!;
+
+        [ObservableProperty]
+        private ICollection<Company> _companyList = [];
+
+        [ObservableProperty]
+        private Company _selectedCompany = null!;
+
+        [ObservableProperty]
+        [Required(ErrorMessage = "用户名不能为空")]
+        [CustomValidation(typeof(RegisterPageViewModel), nameof(ValidateUserName))]
+        private string _userName = string.Empty;
+
+        [ObservableProperty]
+        [Required(ErrorMessage = "密码不能为空")]
+        [CustomValidation(typeof(RegisterPageViewModel), nameof(ValidatePassword))]
+        private string _password = string.Empty;
+
+        [ObservableProperty]
+        [Required(ErrorMessage = "确认密码不能为空")]
+        [CustomValidation(typeof(RegisterPageViewModel), nameof(ValidateConfirmPassword))]
+        private string _confirmPassword = string.Empty;
+
+        private readonly IDataBaseService<User>? _service;
+
+        public RegisterPageViewModel(IDataBaseService<User>? service, SqliteContext context)
+        {
+            _service = service;
+
+            var roles = context.Roles.ToList();
+            foreach (var unitType in UnitTypes)
+            {
+                _roles[unitType.Key] = roles.First(r => r.Name == unitType.Key);
+            }
+
+            CompanyList = context.Companies.ToList();
+
+            Units = context.SupervisionUnits.ToList();
+        }
+
+        [RelayCommand]
+        private async void CreateUser()
+        {
+            ValidateAllProperties();
+
+            if (HasErrors || _service == null) { return; }
+
+            var salt = PasswordHashing.CreateSalt();
+            var user = new User
+            {
+                Salt = salt,
+                Password = PasswordHashing.GenerateSaltedHash(Password, salt),
+                UserName = UserName,
+                LoginName = UserName,
+                CompanyGuid = SelectedCompany.Guid,
+                Company = SelectedCompany,
+                CompanyName = SelectedCompany.Name,
+                IsEnabled = true,
+                RegisterDate = DateTime.Now,
+                Roles = [_roles[SelectedUnitType]],
+                SupervisionUnit = SelectedUnit,
+                SupervisionUnitGuid = SelectedUnit.Guid,
+                IdNumber = string.Empty
+            };
+
+            await _service.InsertAsync(user);
+            if (_service.SaveChanges())
+            {
+                MessageBox.Show("创建成功,跳转到登录页面");
+
+                Login();
+            }
+            else
+            {
+                MessageBox.Show("创建失败!请联系系统管理员");
+            }
+        }
+
+        [RelayCommand]
+        private void Login()
+        {
+            var model = App.Current.Services.GetService<LoginAndRegisterViewModel>();
+            var loginPage = App.Current.Services.GetService<LoginPage>();
+            model?.SwitchPage(loginPage);
+        }
+
+        public static ValidationResult? ValidateUserName(string userName, ValidationContext context)
+        {
+            const string pattern = @"^[a-zA-Z0-9]+$"; // 只允许字母和数字
+            if (!IsMatch(userName, pattern))
+            {
+                return new ValidationResult("只能输入字母和数字");
+            }
+
+            var instance = (RegisterPageViewModel)context.ObjectInstance;
+            var user = instance._service?.Query(x => x.IsEnabled)
+                .FirstOrDefault(x => x.LoginName == userName);
+
+            return user != null ? new ValidationResult("用户已存在") : ValidationResult.Success;
+        }
+
+        public static ValidationResult? ValidatePassword(string userName, ValidationContext context)
+        {
+            const string pattern = @"^[a-zA-Z0-9]+$"; // 只允许字母和数字
+            return !IsMatch(userName, pattern) ? new ValidationResult("只能输入字母和数字") : ValidationResult.Success;
+        }
+
+        public static ValidationResult? ValidateConfirmPassword(string password, ValidationContext context)
+        {
+            var instance = (RegisterPageViewModel)context.ObjectInstance;
+            var isIdentical = instance.Password != instance.ConfirmPassword;
+            return isIdentical ? new ValidationResult("两次输入的密码不相同") : ValidationResult.Success;
+        }
+    }
+}

+ 245 - 0
UniformMaterialManagementSystem/Views/LoginAndRegister/LoginPage.xaml

@@ -0,0 +1,245 @@
+<UserControl
+    x:Class="UniformMaterialManagementSystem.Views.LoginAndRegister.LoginPage"
+    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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    xmlns:utils="clr-namespace:UniformMaterialManagementSystem.Utils"
+    d:DesignHeight="500"
+    d:DesignWidth="800"
+    mc:Ignorable="d">
+
+    <UserControl.Resources>
+        <Style TargetType="TextBox">
+            <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ValidationErrorTemplate}" />
+        </Style>
+        <Style TargetType="PasswordBox">
+            <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ValidationErrorTemplate}" />
+            <Setter Property="Template">
+                <Setter.Value>
+                    <ControlTemplate TargetType="PasswordBox">
+                        <Border
+                            Background="White"
+                            BorderBrush="#019b9b"
+                            BorderThickness="1"
+                            CornerRadius="5">
+                            <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
+                        </Border>
+                    </ControlTemplate>
+                </Setter.Value>
+            </Setter>
+        </Style>
+
+        <BitmapImage x:Key="TeamLogo" UriSource="/Resources/Pictures/TeamLogo.jpg" />
+    </UserControl.Resources>
+
+    <Grid>
+        <Grid.RowDefinitions>
+            <RowDefinition Height="180" />
+            <RowDefinition Height="Auto" />
+            <RowDefinition Height="*" />
+            <RowDefinition Height="30" />
+        </Grid.RowDefinitions>
+
+        <Grid Grid.Row="0">
+            <Grid.Background>
+                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
+                    <GradientStop Offset="0" Color="#e0fffe" />
+                    <GradientStop Offset="0.5" Color="White" />
+                    <GradientStop Offset="1" Color="#e0fffe" />
+                </LinearGradientBrush>
+            </Grid.Background>
+
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="3*" />
+                <ColumnDefinition Width="*" />
+            </Grid.ColumnDefinitions>
+
+            <StackPanel
+                Grid.Row="0"
+                Grid.Column="0"
+                HorizontalAlignment="Right"
+                VerticalAlignment="Center">
+                <Label
+                    HorizontalContentAlignment="Center"
+                    VerticalContentAlignment="Center"
+                    FontFamily="黑体"
+                    FontSize="52"
+                    FontWeight="Bold"
+                    Foreground="#3d9f31">
+                    被装材料管理信息系统
+                </Label>
+                <Label
+                    HorizontalContentAlignment="Center"
+                    VerticalContentAlignment="Center"
+                    FontSize="21"
+                    FontWeight="Bold"
+                    Foreground="LightGray">
+                    BEI ZHUANG CAI LIAO GUAN LI XIN XI XI TONG
+                </Label>
+            </StackPanel>
+
+            <StackPanel Grid.Column="1" VerticalAlignment="Center">
+                <Label
+                    Content="LOGIN"
+                    FontSize="35"
+                    Foreground="LightGray" />
+                <Label
+                    Content="用户登录"
+                    FontSize="30"
+                    FontWeight="Bold"
+                    Foreground="#45bdc0" />
+            </StackPanel>
+
+        </Grid>
+
+        <Border Grid.Row="1" BorderThickness="2">
+            <Border.BorderBrush>
+                <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
+                    <GradientStop Offset="0" Color="White" />
+                    <GradientStop Offset="0.5" Color="#009a9a" />
+                    <GradientStop Offset="1" Color="White" />
+                </LinearGradientBrush>
+            </Border.BorderBrush>
+        </Border>
+
+        <Grid Grid.Row="2">
+            <Grid.Background>
+                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
+                    <GradientStop Offset="0" Color="#e0fffe" />
+                    <GradientStop Offset="1" Color="White" />
+                </LinearGradientBrush>
+            </Grid.Background>
+
+            <Grid Width="500" Margin="0,5">
+                <Grid.RowDefinitions>
+                    <RowDefinition Height="*" />
+                    <RowDefinition Height="*" />
+                    <RowDefinition Height="*" />
+                    <RowDefinition Height="*" />
+                </Grid.RowDefinitions>
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="*" />
+                    <ColumnDefinition Width="3*" />
+                </Grid.ColumnDefinitions>
+
+                <Label
+                    Grid.Row="0"
+                    Grid.Column="0"
+                    HorizontalContentAlignment="Right"
+                    VerticalContentAlignment="Center"
+                    Content="工作年度:"
+                    FontFamily="黑体"
+                    FontSize="20"
+                    Foreground="#0c9ea1" />
+
+                <ComboBox
+                    Grid.Row="0"
+                    Grid.Column="1"
+                    Margin="5,10"
+                    Padding="5,0,0,0"
+                    BorderBrush="#019b9b"
+                    FontSize="20"
+                    ItemsSource="{Binding Years}"
+                    SelectedIndex="0"
+                    SelectedItem="{Binding WorkYear}"
+                    Style="{StaticResource WpfComboBoxStyle}" />
+
+                <Label
+                    Grid.Row="1"
+                    Grid.Column="0"
+                    HorizontalContentAlignment="Right"
+                    VerticalContentAlignment="Center"
+                    Content="用 户 名:"
+                    FontFamily="黑体"
+                    FontSize="20"
+                    Foreground="#0c9ea1" />
+
+                <TextBox
+                    Grid.Row="1"
+                    Grid.Column="1"
+                    Margin="5,10"
+                    HorizontalContentAlignment="Center"
+                    VerticalContentAlignment="Center"
+                    BorderBrush="#019b9b"
+                    FontSize="20"
+                    Text="{Binding UserName, UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True, ValidatesOnDataErrors=True}">
+                    <TextBox.Resources>
+                        <Style TargetType="{x:Type Border}">
+                            <Setter Property="CornerRadius" Value="5" />
+                        </Style>
+                    </TextBox.Resources>
+                </TextBox>
+
+                <Label
+                    Grid.Row="2"
+                    Grid.Column="0"
+                    HorizontalContentAlignment="Right"
+                    VerticalContentAlignment="Center"
+                    Content="密    码:"
+                    FontFamily="黑体"
+                    FontSize="20"
+                    Foreground="#0c9ea1" />
+                <PasswordBox
+                    Grid.Row="2"
+                    Grid.Column="1"
+                    Margin="5,10"
+                    HorizontalContentAlignment="Center"
+                    VerticalContentAlignment="Center"
+                    utils:PasswordHelper.Attach="True"
+                    utils:PasswordHelper.Password="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
+                    BorderBrush="#019b9b"
+                    FontSize="20" />
+
+                <Button
+                    Grid.Row="3"
+                    Grid.Column="0"
+                    Margin="30,10,9,10"
+                    Background="Transparent"
+                    BorderBrush="#03aeae"
+                    BorderThickness="1"
+                    Command="{Binding RegisterCommand}"
+                    CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
+                    FontFamily="黑体"
+                    FontSize="18"
+                    FontWeight="Bold"
+                    Foreground="#0c9ea1">
+                    <Button.Resources>
+                        <Style TargetType="Border">
+                            <Setter Property="CornerRadius" Value="5" />
+                        </Style>
+                    </Button.Resources>
+                    注  册
+                </Button>
+
+                <Button
+                    Grid.Row="3"
+                    Grid.Column="1"
+                    Margin="5,10"
+                    Background="#03aeae"
+                    BorderThickness="0"
+                    Command="{Binding LoginCommand}"
+                    CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
+                    FontFamily="黑体"
+                    FontSize="18"
+                    FontWeight="Bold"
+                    Foreground="White">
+                    <Button.Resources>
+                        <Style TargetType="Border">
+                            <Setter Property="CornerRadius" Value="5" />
+                        </Style>
+                    </Button.Resources>
+                    登  录
+                </Button>
+            </Grid>
+        </Grid>
+
+        <StackPanel
+            Grid.Row="3"
+            Background="#e0fffe"
+            Orientation="Horizontal">
+            <Image Margin="5" Source="{StaticResource TeamLogo}" />
+            <Label VerticalContentAlignment="Center" Content="版权所有-军需能源质量监督总站济南质量监督站(2024)" />
+        </StackPanel>
+    </Grid>
+</UserControl>

+ 16 - 0
UniformMaterialManagementSystem/Views/LoginAndRegister/LoginPage.xaml.cs

@@ -0,0 +1,16 @@
+using System.Windows.Controls;
+
+using UniformMaterialManagementSystem.ViewModels;
+
+namespace UniformMaterialManagementSystem.Views.LoginAndRegister
+{
+    public partial class LoginPage : UserControl
+    {
+        public LoginPage()
+        {
+            InitializeComponent();
+
+            this.DataContext = App.Current.Services.GetService(typeof(LoginPageViewModel));
+        }
+    }
+}

+ 282 - 0
UniformMaterialManagementSystem/Views/LoginAndRegister/RegisterPage.xaml

@@ -0,0 +1,282 @@
+<UserControl
+    x:Class="UniformMaterialManagementSystem.Views.LoginAndRegister.RegisterPage"
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:custom="clr-namespace:UniformMaterialManagementSystem.Custom"
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    xmlns:sys="clr-namespace:System.Collections.Generic;assembly=System.Runtime"
+    xmlns:utils="clr-namespace:UniformMaterialManagementSystem.Utils"
+    d:DesignHeight="500"
+    d:DesignWidth="800"
+    mc:Ignorable="d">
+
+    <UserControl.Resources>
+        <Style TargetType="TextBox">
+            <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ValidationErrorTemplate}" />
+        </Style>
+        <Style TargetType="PasswordBox">
+            <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ValidationErrorTemplate}" />
+            <Setter Property="Template">
+                <Setter.Value>
+                    <ControlTemplate TargetType="PasswordBox">
+                        <Border
+                            Background="White"
+                            BorderBrush="#019b9b"
+                            BorderThickness="1"
+                            CornerRadius="5">
+                            <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
+                        </Border>
+                    </ControlTemplate>
+                </Setter.Value>
+            </Setter>
+        </Style>
+
+    </UserControl.Resources>
+
+    <Grid>
+        <Grid.Background>
+            <LinearGradientBrush StartPoint="1,1" EndPoint="0,0">
+                <GradientStop Offset="0" Color="White" />
+                <GradientStop Offset="0.5" Color="#e0fffe" />
+                <GradientStop Offset="1" Color="White" />
+            </LinearGradientBrush>
+        </Grid.Background>
+
+        <Grid.ColumnDefinitions>
+            <ColumnDefinition Width="*" />
+            <ColumnDefinition Width="2*" />
+        </Grid.ColumnDefinitions>
+
+        <Border Grid.Column="0">
+
+            <Label Template="{DynamicResource Badge}" />
+        </Border>
+
+        <Border Grid.Column="1">
+
+            <Grid>
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="*" />
+                    <ColumnDefinition Width="3*" />
+                    <ColumnDefinition Width="*" />
+                </Grid.ColumnDefinitions>
+
+                <Grid.RowDefinitions>
+                    <RowDefinition Height="*" />
+                    <RowDefinition Height="8*" />
+                    <RowDefinition Height="2*" />
+                </Grid.RowDefinitions>
+
+                <StackPanel
+                    Grid.Row="0"
+                    Grid.Column="1"
+                    VerticalAlignment="Center">
+                    <Label
+                        Content="注册"
+                        FontSize="30"
+                        FontWeight="Bold"
+                        Foreground="#45bdc0" />
+
+                </StackPanel>
+
+                <Grid Grid.Row="1" Grid.Column="1">
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="Auto" />
+                        <RowDefinition />
+                        <RowDefinition Height="Auto" />
+                        <RowDefinition />
+                        <RowDefinition Height="Auto" />
+                        <RowDefinition />
+                        <RowDefinition Height="Auto" />
+                        <RowDefinition />
+                        <RowDefinition Height="Auto" />
+                        <RowDefinition />
+                        <RowDefinition Height="Auto" />
+                        <RowDefinition />
+                    </Grid.RowDefinitions>
+
+                    <Label
+                        Grid.Row="0"
+                        Grid.Column="0"
+                        HorizontalContentAlignment="Left"
+                        VerticalContentAlignment="Center"
+                        Content="单位类型:"
+                        FontFamily="黑体"
+                        FontSize="12"
+                        Foreground="#0c9ea1" />
+
+                    <ComboBox
+                        Grid.Row="1"
+                        Padding="5,0,0,0"
+                        BorderBrush="#019b9b"
+                        ItemsSource="{Binding UnitTypes}"
+                        SelectedValue="{Binding SelectedUnitType}"
+                        SelectedValuePath="Key"
+                        Style="{StaticResource WpfComboBoxStyle}">
+                        <ComboBox.ItemTemplate>
+                            <DataTemplate DataType="{x:Type sys:KeyValuePair`2}">
+                                <Label
+                                    VerticalAlignment="Center"
+                                    VerticalContentAlignment="Center"
+                                    Content="{Binding Value}" />
+                            </DataTemplate>
+                        </ComboBox.ItemTemplate>
+                    </ComboBox>
+
+                    <Label
+                        Grid.Row="2"
+                        Grid.Column="0"
+                        HorizontalContentAlignment="Left"
+                        VerticalContentAlignment="Center"
+                        Content="监管单位:"
+                        FontFamily="黑体"
+                        FontSize="12"
+                        Foreground="#0c9ea1" />
+
+                    <custom:FilterableComboBox
+                        Grid.Row="3"
+                        Padding="5,0,0,0"
+                        VerticalContentAlignment="Center"
+                        BorderBrush="#019b9b"
+                        DisplayMemberPath="Name"
+                        ItemsSource="{Binding Units}"
+                        SelectedItem="{Binding SelectedUnit}"
+                        Style="{StaticResource WpfComboBoxStyle}" />
+
+                    <Label
+                        Grid.Row="4"
+                        Grid.Column="0"
+                        HorizontalContentAlignment="Left"
+                        VerticalContentAlignment="Center"
+                        Content="单位名称:"
+                        FontFamily="黑体"
+                        FontSize="12"
+                        Foreground="#0c9ea1" />
+
+                    <custom:FilterableComboBox
+                        Grid.Row="5"
+                        Padding="5,0,0,0"
+                        BorderBrush="#019b9b"
+                        DisplayMemberPath="Name"
+                        ItemsSource="{Binding CompanyList}"
+                        SelectedItem="{Binding SelectedCompany}"
+                        Style="{StaticResource WpfComboBoxStyle}" />
+
+                    <Label
+                        Grid.Row="6"
+                        Grid.Column="0"
+                        HorizontalContentAlignment="Left"
+                        VerticalContentAlignment="Center"
+                        Content="用 户 名:"
+                        FontFamily="黑体"
+                        FontSize="12"
+                        Foreground="#0c9ea1" />
+
+                    <TextBox
+                        Grid.Row="7"
+                        HorizontalContentAlignment="Center"
+                        VerticalContentAlignment="Center"
+                        BorderBrush="#019b9b"
+                        FontSize="14"
+                        Text="{Binding UserName, UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True, ValidatesOnDataErrors=True}">
+                        <TextBox.Resources>
+                            <Style TargetType="{x:Type Border}">
+                                <Setter Property="CornerRadius" Value="5" />
+                            </Style>
+                        </TextBox.Resources>
+                    </TextBox>
+
+                    <Label
+                        Grid.Row="8"
+                        Grid.Column="0"
+                        HorizontalContentAlignment="Left"
+                        VerticalContentAlignment="Center"
+                        Content="密    码:"
+                        FontFamily="黑体"
+                        FontSize="12"
+                        Foreground="#0c9ea1" />
+
+                    <PasswordBox
+                        Grid.Row="9"
+                        HorizontalContentAlignment="Center"
+                        VerticalContentAlignment="Center"
+                        utils:PasswordHelper.Attach="True"
+                        utils:PasswordHelper.Password="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
+                        BorderBrush="#019b9b"
+                        FontSize="14">
+                        <PasswordBox.Resources>
+                            <Style TargetType="{x:Type Border}">
+                                <Setter Property="CornerRadius" Value="5" />
+                            </Style>
+                        </PasswordBox.Resources>
+                    </PasswordBox>
+
+                    <Label
+                        Grid.Row="10"
+                        Grid.Column="0"
+                        HorizontalContentAlignment="Left"
+                        VerticalContentAlignment="Center"
+                        Content="密码确认:"
+                        FontFamily="黑体"
+                        FontSize="12"
+                        Foreground="#0c9ea1" />
+
+                    <PasswordBox
+                        Grid.Row="11"
+                        HorizontalContentAlignment="Center"
+                        VerticalContentAlignment="Center"
+                        utils:PasswordHelper.Attach="True"
+                        utils:PasswordHelper.Password="{Binding ConfirmPassword, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
+                        BorderBrush="#019b9b"
+                        FontSize="14">
+                        <PasswordBox.Resources>
+                            <Style TargetType="{x:Type Border}">
+                                <Setter Property="CornerRadius" Value="5" />
+                            </Style>
+                        </PasswordBox.Resources>
+                    </PasswordBox>
+                </Grid>
+
+                <Grid
+                    Grid.Row="2"
+                    Grid.Column="1"
+                    Margin="0,20,0,0">
+
+                    <Grid.RowDefinitions>
+                        <RowDefinition />
+                        <RowDefinition />
+                    </Grid.RowDefinitions>
+
+                    <Button
+                        Background="#03aeae"
+                        BorderThickness="0"
+                        Command="{Binding CreateUserCommand}"
+                        CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
+                        FontFamily="黑体"
+                        FontSize="18"
+                        FontWeight="Bold"
+                        Foreground="White">
+                        <Button.Resources>
+                            <Style TargetType="Border">
+                                <Setter Property="CornerRadius" Value="5" />
+                            </Style>
+                        </Button.Resources>
+                        创建账户
+                    </Button>
+                    <StackPanel Grid.Row="1" Orientation="Horizontal">
+                        <TextBlock Margin="5,0,0,0" Text="已经有账户?" />
+                        <TextBlock>
+                            <Hyperlink
+                                Command="{Binding LoginCommand}"
+                                Foreground="#03aeae"
+                                TextDecorations="Underline">
+                                登录
+                            </Hyperlink>
+                        </TextBlock>
+                    </StackPanel>
+                </Grid>
+            </Grid>
+        </Border>
+    </Grid>
+</UserControl>

+ 16 - 0
UniformMaterialManagementSystem/Views/LoginAndRegister/RegisterPage.xaml.cs

@@ -0,0 +1,16 @@
+using System.Windows.Controls;
+
+using UniformMaterialManagementSystem.ViewModels;
+
+namespace UniformMaterialManagementSystem.Views.LoginAndRegister
+{
+    public partial class RegisterPage : UserControl
+    {
+        public RegisterPage()
+        {
+            InitializeComponent();
+
+            DataContext = App.Current.Services.GetService(typeof(RegisterPageViewModel));
+        }
+    }
+}

+ 34 - 0
UniformMaterialManagementSystem/Views/LoginAndRegisterWindow.xaml

@@ -0,0 +1,34 @@
+<Window
+    x:Class="UniformMaterialManagementSystem.Views.LoginAndRegisterWindow"
+    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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+    Width="800"
+    Height="500"
+    Background="Transparent"
+    ResizeMode="NoResize"
+    WindowStartupLocation="CenterScreen"
+    WindowStyle="None"
+    mc:Ignorable="d">
+
+    <WindowChrome.WindowChrome>
+        <WindowChrome CaptionHeight="0" GlassFrameThickness="-1" />
+    </WindowChrome.WindowChrome>
+
+    <Border
+        Margin="10"
+        Background="GhostWhite"
+        BorderBrush="#009a9a"
+        BorderThickness="5"
+        CornerRadius="5">
+        <Border.Effect>
+            <DropShadowEffect
+                BlurRadius="10"
+                Opacity="0.5"
+                ShadowDepth="0"
+                Color="Black" />
+        </Border.Effect>
+        <ContentControl Content="{Binding CurrentView}" />
+    </Border>
+</Window>

+ 3 - 3
UniformMaterialManagementSystem/Views/LoginPage.xaml.cs → UniformMaterialManagementSystem/Views/LoginAndRegisterWindow.xaml.cs

@@ -5,13 +5,13 @@ using UniformMaterialManagementSystem.ViewModels;
 
 namespace UniformMaterialManagementSystem.Views
 {
-    public partial class LoginPage : Window
+    public partial class LoginAndRegisterWindow : Window
     {
-        public LoginPage()
+        public LoginAndRegisterWindow()
         {
             InitializeComponent();
 
-            this.DataContext = App.Current.Services.GetService(typeof(LoginPageViewModel));
+            DataContext = App.Current.Services.GetService(typeof(LoginAndRegisterViewModel));
         }
 
         /// <summary>

+ 0 - 267
UniformMaterialManagementSystem/Views/LoginPage.xaml

@@ -1,267 +0,0 @@
-<Window
-    x:Class="UniformMaterialManagementSystem.Views.LoginPage"
-    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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
-    xmlns:utils="clr-namespace:UniformMaterialManagementSystem.Utils"
-    Width="800"
-    Height="500"
-    Background="Transparent"
-    ResizeMode="NoResize"
-    WindowStartupLocation="CenterScreen"
-    WindowStyle="None"
-    mc:Ignorable="d">
-
-    <WindowChrome.WindowChrome>
-        <WindowChrome CaptionHeight="0" GlassFrameThickness="-1" />
-    </WindowChrome.WindowChrome>
-
-    <Window.Resources>
-        <Style TargetType="TextBox">
-            <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ValidationErrorTemplate}" />
-        </Style>
-        <Style TargetType="PasswordBox">
-            <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ValidationErrorTemplate}" />
-            <Setter Property="Template">
-                <Setter.Value>
-                    <ControlTemplate TargetType="PasswordBox">
-                        <Border
-                            Background="White"
-                            BorderBrush="#019b9b"
-                            BorderThickness="1"
-                            CornerRadius="5">
-                            <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
-                        </Border>
-                    </ControlTemplate>
-                </Setter.Value>
-            </Setter>
-        </Style>
-
-        <BitmapImage x:Key="TeamLogo" UriSource="../Resources/Pictures/TeamLogo.jpg" />
-    </Window.Resources>
-
-    <Border
-        Margin="10"
-        Background="GhostWhite"
-        BorderBrush="#009a9a"
-        BorderThickness="5"
-        CornerRadius="5">
-        <Border.Effect>
-            <DropShadowEffect
-                BlurRadius="10"
-                Opacity="0.5"
-                ShadowDepth="0"
-                Color="Black" />
-        </Border.Effect>
-        <Grid>
-            <Grid.RowDefinitions>
-                <RowDefinition Height="180" />
-                <RowDefinition Height="Auto" />
-                <RowDefinition Height="*" />
-                <RowDefinition Height="30" />
-            </Grid.RowDefinitions>
-
-            <Grid Grid.Row="0">
-                <Grid.Background>
-                    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
-                        <GradientStop Offset="0" Color="#e0fffe" />
-                        <GradientStop Offset="0.5" Color="White" />
-                        <GradientStop Offset="1" Color="#e0fffe" />
-                    </LinearGradientBrush>
-                </Grid.Background>
-
-                <Grid.ColumnDefinitions>
-                    <ColumnDefinition Width="3*" />
-                    <ColumnDefinition Width="*" />
-                </Grid.ColumnDefinitions>
-
-                <StackPanel
-                    Grid.Row="0"
-                    Grid.Column="0"
-                    HorizontalAlignment="Right"
-                    VerticalAlignment="Center">
-                    <Label
-                        HorizontalContentAlignment="Center"
-                        VerticalContentAlignment="Center"
-                        FontFamily="黑体"
-                        FontSize="60"
-                        FontWeight="Bold"
-                        Foreground="#3d9f31">
-                        被装材料业务系统
-                    </Label>
-                    <Label
-                        HorizontalContentAlignment="Center"
-                        VerticalContentAlignment="Center"
-                        FontSize="24"
-                        FontWeight="Bold"
-                        Foreground="LightGray">
-                        BEI ZHUANG CAI LIAO YE WU XI TONG
-                    </Label>
-                </StackPanel>
-
-                <StackPanel Grid.Column="1" VerticalAlignment="Center">
-                    <Label
-                        Content="LOGIN"
-                        FontSize="35"
-                        Foreground="LightGray" />
-                    <Label
-                        Content="用户登录"
-                        FontSize="30"
-                        FontWeight="Bold"
-                        Foreground="#45bdc0" />
-                </StackPanel>
-
-            </Grid>
-
-            <Border Grid.Row="1" BorderThickness="2">
-                <Border.BorderBrush>
-                    <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
-                        <GradientStop Offset="0" Color="White" />
-                        <GradientStop Offset="0.5" Color="#009a9a" />
-                        <GradientStop Offset="1" Color="White" />
-                    </LinearGradientBrush>
-                </Border.BorderBrush>
-            </Border>
-
-            <Grid Grid.Row="2">
-                <Grid.Background>
-                    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
-                        <GradientStop Offset="0" Color="#e0fffe" />
-                        <GradientStop Offset="1" Color="White" />
-                    </LinearGradientBrush>
-                </Grid.Background>
-
-                <Grid Width="500" Margin="0,5">
-                    <Grid.RowDefinitions>
-                        <RowDefinition Height="*" />
-                        <RowDefinition Height="*" />
-                        <RowDefinition Height="*" />
-                        <RowDefinition Height="*" />
-                    </Grid.RowDefinitions>
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition Width="*" />
-                        <ColumnDefinition Width="3*" />
-                    </Grid.ColumnDefinitions>
-
-                    <Label
-                        Grid.Row="0"
-                        Grid.Column="0"
-                        HorizontalContentAlignment="Right"
-                        VerticalContentAlignment="Center"
-                        Content="工作年度:"
-                        FontFamily="黑体"
-                        FontSize="20"
-                        Foreground="#0c9ea1" />
-
-                    <ComboBox
-                        Grid.Row="0"
-                        Grid.Column="1"
-                        Margin="5,10"
-                        Padding="5,0,0,0"
-                        BorderBrush="#019b9b"
-                        FontSize="20"
-                        ItemsSource="{Binding Years}"
-                        SelectedIndex="0"
-                        SelectedItem="{Binding WorkYear}"
-                        Style="{StaticResource WpfComboBoxStyle}" />
-
-                    <Label
-                        Grid.Row="1"
-                        Grid.Column="0"
-                        HorizontalContentAlignment="Right"
-                        VerticalContentAlignment="Center"
-                        Content="用 户 名:"
-                        FontFamily="黑体"
-                        FontSize="20"
-                        Foreground="#0c9ea1" />
-
-                    <TextBox
-                        Grid.Row="1"
-                        Grid.Column="1"
-                        Margin="5,10"
-                        HorizontalContentAlignment="Center"
-                        VerticalContentAlignment="Center"
-                        BorderBrush="#019b9b"
-                        FontSize="20"
-                        Text="{Binding UserName, UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True, ValidatesOnDataErrors=True}">
-                        <TextBox.Resources>
-                            <Style TargetType="{x:Type Border}">
-                                <Setter Property="CornerRadius" Value="5" />
-                            </Style>
-                        </TextBox.Resources>
-                    </TextBox>
-
-                    <Label
-                        Grid.Row="2"
-                        Grid.Column="0"
-                        HorizontalContentAlignment="Right"
-                        VerticalContentAlignment="Center"
-                        Content="密    码:"
-                        FontFamily="黑体"
-                        FontSize="20"
-                        Foreground="#0c9ea1" />
-                    <PasswordBox
-                        Grid.Row="2"
-                        Grid.Column="1"
-                        Margin="5,10"
-                        HorizontalContentAlignment="Center"
-                        VerticalContentAlignment="Center"
-                        utils:PasswordHelper.Attach="True"
-                        utils:PasswordHelper.Password="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
-                        BorderBrush="#019b9b"
-                        FontSize="20" />
-
-                    <Button
-                        Grid.Row="3"
-                        Grid.Column="0"
-                        Margin="30,10,9,10"
-                        Background="Transparent"
-                        BorderBrush="#03aeae"
-                        BorderThickness="1"
-                        Command="{Binding CancelCommand}"
-                        CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
-                        FontFamily="黑体"
-                        FontSize="18"
-                        FontWeight="Bold"
-                        Foreground="#0c9ea1">
-                        <Button.Resources>
-                            <Style TargetType="Border">
-                                <Setter Property="CornerRadius" Value="5" />
-                            </Style>
-                        </Button.Resources>
-                        注  册
-                    </Button>
-
-                    <Button
-                        Grid.Row="3"
-                        Grid.Column="1"
-                        Margin="5,10"
-                        Background="#03aeae"
-                        BorderThickness="0"
-                        Command="{Binding LoginCommand}"
-                        CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
-                        FontFamily="黑体"
-                        FontSize="18"
-                        FontWeight="Bold"
-                        Foreground="White">
-                        <Button.Resources>
-                            <Style TargetType="Border">
-                                <Setter Property="CornerRadius" Value="5" />
-                            </Style>
-                        </Button.Resources>
-                        登  录
-                    </Button>
-                </Grid>
-            </Grid>
-
-            <StackPanel
-                Grid.Row="3"
-                Background="#e0fffe"
-                Orientation="Horizontal">
-                <Image Margin="5" Source="{StaticResource TeamLogo}" />
-                <Label VerticalContentAlignment="Center" Content="版权所有-军需能源质量监督总站济南质量监督站(2024)" />
-            </StackPanel>
-        </Grid>
-    </Border>
-</Window>