feat: 初始功能

This commit is contained in:
Shiqvlizi Name
2026-05-23 18:16:50 +08:00
parent a5bfd8792e
commit 9a51259e9e
63 changed files with 5377 additions and 1 deletions

65
Views/LibraryView.xaml Normal file
View File

@@ -0,0 +1,65 @@
<UserControl x:Class="CloudPrint.Client.Views.LibraryView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="260" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Background="White" CornerRadius="14" Padding="18" Margin="0,0,16,0">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Margin="0,0,0,12">
<TextBlock Text="文库分类" FontSize="18" FontWeight="Bold" />
<TextBlock Text="本地文库会按分类复制保存,连接后可同步上传到云端。" TextWrapping="Wrap" Foreground="#64748B" Margin="0,6,0,0" />
</StackPanel>
<ListBox ItemsSource="{Binding Categories}"
SelectedItem="{Binding SelectedCategory}"
BorderThickness="0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="{Binding Icon}" Margin="0,0,8,0" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
</Border>
<Border Grid.Column="1" Background="White" CornerRadius="14" Padding="18">
<DockPanel>
<Grid DockPanel.Dock="Top" Margin="0,0,0,12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel>
<TextBlock Text="文库文件" FontSize="18" FontWeight="Bold" />
<TextBlock Text="{Binding StatusMessage}" Foreground="#64748B" Margin="0,4,0,0" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
<Button Content="加入文件" Command="{Binding AddDocumentCommand}" />
<Button Content="同步选中" Command="{Binding SyncSelectedCommand}" />
<Button Content="同步全部" Command="{Binding SyncAllCommand}" />
<Button Content="移除" Command="{Binding RemoveDocumentCommand}" Style="{StaticResource SecondaryButtonStyle}" />
</StackPanel>
</Grid>
<DataGrid ItemsSource="{Binding Documents}" SelectedItem="{Binding SelectedDocument}">
<DataGrid.Columns>
<DataGridTextColumn Header="标题" Binding="{Binding Title, UpdateSourceTrigger=PropertyChanged}" Width="1.4*" />
<DataGridTextColumn Header="分类" Binding="{Binding CategoryName}" Width="110" />
<DataGridTextColumn Header="文件名" Binding="{Binding FileName}" Width="1.4*" />
<DataGridTextColumn Header="类型" Binding="{Binding FileType}" Width="70" />
<DataGridTextColumn Header="大小" Binding="{Binding FileSizeText}" Width="90" />
<DataGridTextColumn Header="描述" Binding="{Binding Description, UpdateSourceTrigger=PropertyChanged}" Width="1.5*" />
<DataGridTextColumn Header="同步状态" Binding="{Binding SyncStatus}" Width="90" />
</DataGrid.Columns>
</DataGrid>
</DockPanel>
</Border>
</Grid>
</UserControl>

View File

@@ -0,0 +1,9 @@
namespace CloudPrint.Client.Views;
public partial class LibraryView : System.Windows.Controls.UserControl
{
public LibraryView()
{
InitializeComponent();
}
}

89
Views/MainWindow.xaml Normal file
View File

@@ -0,0 +1,89 @@
<Window x:Class="CloudPrint.Client.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:CloudPrint.Client.Views"
Title="云印享打印客户端"
Width="1200"
Height="760"
MinWidth="980"
MinHeight="620"
WindowStartupLocation="CenterScreen">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="#2563EB" CornerRadius="18" Padding="24" Margin="0,0,0,16">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel>
<TextBlock Text="云印享 Windows 打印客户端" FontSize="26" FontWeight="Bold" Foreground="White" />
<TextBlock Text="gRPC 订阅打印任务 · Windows 打印机管理 · 文件预处理(最小运行版)"
Margin="0,8,0,0" Foreground="#DBEAFE" FontSize="14" />
</StackPanel>
<Border Grid.Column="1" Background="#1D4ED8" CornerRadius="12" Padding="14,8" VerticalAlignment="Center">
<TextBlock Text="{Binding ConnectionStatus}" Foreground="White" FontWeight="SemiBold" />
</Border>
</Grid>
</Border>
<Border Grid.Row="1" Background="White" CornerRadius="14" Padding="18" Margin="0,0,0,16">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1.15*" />
<ColumnDefinition Width="1.05*" />
<ColumnDefinition Width="1.05*" />
<ColumnDefinition Width="1.25*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Margin="0,0,14,0">
<TextBlock Text="gRPC 服务器地址" Foreground="#475569" Margin="0,0,0,6" />
<TextBox Text="{Binding Settings.ServerAddress, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
<StackPanel Grid.Column="1" Margin="0,0,14,0">
<TextBlock Text="打印客户端 API Key" Foreground="#475569" Margin="0,0,0,6" />
<TextBox Text="{Binding Settings.ApiKey, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
<StackPanel Grid.Column="2" Margin="0,0,14,0">
<TextBlock Text="门店名称" Foreground="#475569" Margin="0,0,0,6" />
<TextBox Text="{Binding Settings.StoreName, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
<StackPanel Grid.Column="3" Margin="0,0,14,0">
<TextBlock Text="本机打印机" Foreground="#475569" Margin="0,0,0,6" />
<ComboBox ItemsSource="{Binding Printers}"
SelectedItem="{Binding SelectedPrinter}"
DisplayMemberPath="DisplayText"
MinHeight="32" />
</StackPanel>
<StackPanel Grid.Column="4" VerticalAlignment="Bottom" Orientation="Horizontal">
<Button Content="保存设置" Command="{Binding SaveSettingsCommand}" Style="{StaticResource SecondaryButtonStyle}" />
<Button Content="刷新打印机" Command="{Binding RefreshPrintersCommand}" Style="{StaticResource SecondaryButtonStyle}" />
<Button Content="连接/注册" Command="{Binding ConnectCommand}" />
<Button Content="订阅任务" Command="{Binding SubscribeCommand}" />
<Button Content="断开" Command="{Binding DisconnectCommand}" Style="{StaticResource SecondaryButtonStyle}" />
</StackPanel>
</Grid>
</Border>
<TabControl Grid.Row="2" Background="Transparent" BorderThickness="0">
<TabItem Header="打印队列">
<views:PrintQueueView DataContext="{Binding}" Margin="0,12,0,0" />
</TabItem>
<TabItem Header="文库管理">
<views:LibraryView DataContext="{Binding Library}" Margin="0,12,0,0" />
</TabItem>
<TabItem Header="系统设置">
<views:SettingsView DataContext="{Binding SettingsPanel}" Margin="0,12,0,0" />
</TabItem>
</TabControl>
<TextBlock Grid.Row="3" Text="当前仅修改 Client 目录;未触碰 adminpage/backend/frontend。"
Foreground="#64748B" Margin="0,12,0,0" HorizontalAlignment="Right" />
</Grid>
</Window>

13
Views/MainWindow.xaml.cs Normal file
View File

@@ -0,0 +1,13 @@
using System.Windows;
using CloudPrint.Client.ViewModels;
namespace CloudPrint.Client.Views;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
}

89
Views/PrintQueueView.xaml Normal file
View File

@@ -0,0 +1,89 @@
<UserControl x:Class="CloudPrint.Client.Views.PrintQueueView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Background="White" CornerRadius="14" Padding="18" Margin="0,0,16,0">
<DockPanel>
<Grid DockPanel.Dock="Top" Margin="0,0,0,12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel>
<TextBlock Text="打印任务队列" FontSize="18" FontWeight="Bold" />
<TextBlock Text="后端 SubscribeJobs 流进入队列,客户端预处理后提交打印并上报 ReportJobStatus。"
Foreground="#64748B" Margin="0,4,0,0" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
<CheckBox Content="自动处理" IsChecked="{Binding AutoProcessQueue}" VerticalAlignment="Center" Margin="0,0,8,0" />
<Button Content="暂停队列" Command="{Binding PauseQueueCommand}" Style="{StaticResource SecondaryButtonStyle}" />
<Button Content="恢复队列" Command="{Binding ResumeQueueCommand}" Style="{StaticResource SecondaryButtonStyle}" />
<Button Content="处理下一任务" Command="{Binding ProcessSelectedJobCommand}" />
<Button Content="取消选中" Command="{Binding CancelSelectedJobCommand}" Style="{StaticResource SecondaryButtonStyle}" />
</StackPanel>
</Grid>
<TextBlock DockPanel.Dock="Top"
Text="{Binding QueueStatusText}"
Foreground="#2563EB"
Margin="0,0,0,10" />
<DataGrid ItemsSource="{Binding Jobs}" SelectedItem="{Binding SelectedJob}">
<DataGrid.Columns>
<DataGridTextColumn Header="任务号" Binding="{Binding JobNo}" Width="155" />
<DataGridTextColumn Header="文件" Binding="{Binding FileName}" Width="*" />
<DataGridTextColumn Header="打印机" Binding="{Binding PrinterName}" Width="160" />
<DataGridTextColumn Header="份数" Binding="{Binding Copies}" Width="65" />
<DataGridCheckBoxColumn Header="彩色" Binding="{Binding Color}" Width="65" />
<DataGridCheckBoxColumn Header="双面" Binding="{Binding Duplex}" Width="65" />
<DataGridTextColumn Header="页码" Binding="{Binding PageRange}" Width="70" />
<DataGridTextColumn Header="系统Job" Binding="{Binding WindowsJobId}" Width="80" />
<DataGridTextColumn Header="系统状态" Binding="{Binding WindowsJobStatus}" Width="110" />
<DataGridTextColumn Header="状态" Binding="{Binding StatusText}" Width="90" />
<DataGridTextColumn Header="进度" Binding="{Binding Progress, StringFormat={}{0}%}" Width="75" />
<DataGridTextColumn Header="错误" Binding="{Binding ErrorMessage}" Width="160" />
</DataGrid.Columns>
</DataGrid>
</DockPanel>
</Border>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="White" CornerRadius="14" Padding="18" Margin="0,0,0,16">
<StackPanel>
<TextBlock Text="运行设置" FontSize="18" FontWeight="Bold" />
<TextBlock Text="真实打印链路:注册打印机 → 订阅任务 → 下载/处理文件 → 调用 Windows 打印服务 → 上报状态。"
TextWrapping="Wrap" Foreground="#64748B" Margin="0,12,0,0" />
</StackPanel>
</Border>
<Border Grid.Row="1" Background="White" CornerRadius="14" Padding="18">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Margin="0,0,0,12">
<DockPanel>
<TextBlock Text="运行日志" FontSize="18" FontWeight="Bold" DockPanel.Dock="Left" />
<Button Content="清空" Command="{Binding ClearLogsCommand}" Style="{StaticResource SecondaryButtonStyle}" DockPanel.Dock="Right" />
</DockPanel>
<TextBlock Text="{Binding LastMessage}" Foreground="#64748B" TextWrapping="Wrap" Margin="0,4,0,0" />
</StackPanel>
<ListBox ItemsSource="{Binding Logs}" BorderThickness="0" FontFamily="Consolas" FontSize="12">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DisplayText}" TextWrapping="Wrap" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
</Border>
</Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,9 @@
namespace CloudPrint.Client.Views;
public partial class PrintQueueView : System.Windows.Controls.UserControl
{
public PrintQueueView()
{
InitializeComponent();
}
}

77
Views/SettingsView.xaml Normal file
View File

@@ -0,0 +1,77 @@
<UserControl x:Class="CloudPrint.Client.Views.SettingsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Border Background="White" CornerRadius="14" Padding="22">
<Grid MaxWidth="820" HorizontalAlignment="Left">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.ColumnSpan="3" Margin="0,0,0,20">
<TextBlock Text="系统设置" FontSize="20" FontWeight="Bold" />
<TextBlock Text="配置真实后端地址、打印客户端 API Key、本地文库目录API Key 和 token 会用 Windows DPAPI 加密保存。"
Foreground="#64748B" Margin="0,6,0,0" />
</StackPanel>
<TextBlock Grid.Row="1" Grid.Column="0" Text="服务器地址" VerticalAlignment="Center" Margin="0,0,12,12" />
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Settings.ServerAddress, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12" />
<TextBlock Grid.Row="2" Grid.Column="0" Text="API Key" VerticalAlignment="Center" Margin="0,0,12,12" />
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Settings.ApiKey, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12" />
<TextBlock Grid.Row="3" Grid.Column="0" Text="门店名称" VerticalAlignment="Center" Margin="0,0,12,12" />
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Settings.StoreName, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,0,12" />
<TextBlock Grid.Row="4" Grid.Column="0" Text="本地文库目录" VerticalAlignment="Center" Margin="0,0,12,12" />
<TextBox Grid.Row="4" Grid.Column="1" Text="{Binding Settings.LibraryRoot, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,8,12" />
<Button Grid.Row="4" Grid.Column="2" Content="选择" Command="{Binding SelectLibraryRootCommand}" Margin="0,0,0,12" />
<StackPanel Grid.Row="5" Grid.Column="1" Orientation="Horizontal" Margin="0,4,0,0">
<CheckBox Content="允许 HTTP gRPC" IsChecked="{Binding Settings.AllowInsecureGrpc}" VerticalAlignment="Center" Margin="0,0,24,0" />
<TextBlock Text="最大上传 MB" VerticalAlignment="Center" Margin="0,0,8,0" />
<TextBox Text="{Binding Settings.MaxUploadSizeMb, UpdateSourceTrigger=PropertyChanged}" Width="70" Margin="0,0,16,0" />
<TextBlock Text="心跳秒" VerticalAlignment="Center" Margin="0,0,8,0" />
<TextBox Text="{Binding Settings.HeartbeatIntervalSeconds, UpdateSourceTrigger=PropertyChanged}" Width="55" Margin="0,0,16,0" />
<Button Content="保存设置" Command="{Binding SaveCommand}" />
<TextBlock Text="{Binding StatusMessage}" Foreground="#64748B" VerticalAlignment="Center" Margin="8,0,0,0" />
</StackPanel>
<StackPanel Grid.Row="6" Grid.Column="1" Orientation="Horizontal" Margin="0,12,0,0">
<TextBlock Text="日志目录" VerticalAlignment="Center" Margin="0,0,8,0" />
<TextBlock Text="{Binding LogDirectory}" Foreground="#64748B" VerticalAlignment="Center" Margin="0,0,12,0" />
<Button Content="打开日志目录" Command="{Binding OpenLogDirectoryCommand}" Style="{StaticResource SecondaryButtonStyle}" />
</StackPanel>
<Separator Grid.Row="7" Grid.ColumnSpan="3" Margin="0,22,0,18" />
<StackPanel Grid.Row="8" Grid.ColumnSpan="3" Margin="0,0,0,14">
<TextBlock Text="管理员登录" FontSize="18" FontWeight="Bold" />
<TextBlock Text="登录后会保存 access token并在真实 gRPC 请求中附加 Authorization metadata。"
Foreground="#64748B" Margin="0,6,0,0" />
</StackPanel>
<TextBlock Grid.Row="9" Grid.Column="0" Text="管理员账号" VerticalAlignment="Center" Margin="0,0,12,0" />
<StackPanel Grid.Row="9" Grid.Column="1" Grid.ColumnSpan="2" Orientation="Horizontal">
<TextBox Text="{Binding Settings.AdminUsername, UpdateSourceTrigger=PropertyChanged}" Width="180" Margin="0,0,10,0" />
<PasswordBox x:Name="PART_AdminPasswordBox" Width="180" PasswordChanged="AdminPasswordBox_OnPasswordChanged" Margin="0,0,10,0" />
<Button Content="登录" Command="{Binding LoginAdminCommand}" />
<Button Content="退出" Command="{Binding LogoutAdminCommand}" Style="{StaticResource SecondaryButtonStyle}" />
<TextBlock Text="{Binding AdminLoginStatus}" Foreground="#64748B" VerticalAlignment="Center" Margin="8,0,0,0" />
</StackPanel>
</Grid>
</Border>
</UserControl>

View File

@@ -0,0 +1,17 @@
namespace CloudPrint.Client.Views;
public partial class SettingsView : System.Windows.Controls.UserControl
{
public SettingsView()
{
InitializeComponent();
}
private void AdminPasswordBox_OnPasswordChanged(object sender, System.Windows.RoutedEventArgs e)
{
if (DataContext is ViewModels.SettingsViewModel viewModel && sender is System.Windows.Controls.PasswordBox passwordBox)
{
viewModel.AdminPassword = passwordBox.Password;
}
}
}