添加主界面
This commit is contained in:
@@ -1,19 +1,21 @@
|
||||
using LAEPS.ViewModels;
|
||||
using Castle.DynamicProxy;
|
||||
using Common;
|
||||
using LAEPS.ViewModels;
|
||||
using LAEPS.ViewModels.Dialogs;
|
||||
using LAEPS.Views;
|
||||
using LAEPS.Views.Dialogs;
|
||||
using Castle.DynamicProxy;
|
||||
using LAEPS.Views;
|
||||
using LAEPS.Views.Dialogs;
|
||||
using Logger;
|
||||
using Notifications.Wpf.Core;
|
||||
using ORM;
|
||||
using Service.Implement;
|
||||
using Service.Interface;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
using UIShare.PubEvent;
|
||||
using Notifications.Wpf.Core;
|
||||
using Logger;
|
||||
using Common;
|
||||
using ORM;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
|
||||
namespace LAEPS
|
||||
{
|
||||
@@ -69,6 +71,8 @@ namespace LAEPS
|
||||
// 注册通知管理器
|
||||
INotificationManager NotificationManager = new NotificationManager();
|
||||
containerRegistry.RegisterInstance<INotificationManager>(NotificationManager);
|
||||
// 注册服务
|
||||
containerRegistry.RegisterSingleton<IPostService, PostService>();
|
||||
}
|
||||
//指定模块加载方式(需要手动将模块生成的dll放入Modules文件夹中)
|
||||
protected override IModuleCatalog CreateModuleCatalog()
|
||||
@@ -77,17 +81,16 @@ namespace LAEPS
|
||||
return new DirectoryModuleCatalog() { ModulePath = @".\Modules" };
|
||||
}
|
||||
//手动模块加载方式
|
||||
//protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
|
||||
//{
|
||||
// Type moduleAType = typeof(LoginModule.LoginModule);
|
||||
// moduleCatalog.AddModule(new ModuleInfo()
|
||||
// {
|
||||
// ModuleName = moduleAType.Name,
|
||||
// ModuleType = moduleAType.AssemblyQualifiedName,
|
||||
// InitializationMode = InitializationMode.OnDemand
|
||||
// });
|
||||
|
||||
// base.ConfigureModuleCatalog(moduleCatalog);
|
||||
//}
|
||||
}
|
||||
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
|
||||
{
|
||||
Type moduleAType = typeof(MainModule.MainModule);
|
||||
moduleCatalog.AddModule(new ModuleInfo()
|
||||
{
|
||||
ModuleName = moduleAType.Name,
|
||||
ModuleType = moduleAType.AssemblyQualifiedName,
|
||||
InitializationMode = InitializationMode.OnDemand
|
||||
});
|
||||
base.ConfigureModuleCatalog(moduleCatalog);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,12 +41,14 @@ namespace LAEPS.ViewModels
|
||||
private IRegionManager _regionManager;
|
||||
private IContainerProvider _containerProvider;
|
||||
private INotificationManager _notificationManager;
|
||||
private IModuleManager _moduleManager;
|
||||
public ShellViewModel( IContainerProvider containerProvider)
|
||||
{
|
||||
_containerProvider= containerProvider;
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
_regionManager = containerProvider.Resolve<IRegionManager>();
|
||||
_notificationManager = containerProvider.Resolve<INotificationManager>();
|
||||
_moduleManager = containerProvider.Resolve<IModuleManager>();
|
||||
LeftDrawerOpenCommand = new DelegateCommand(LeftDrawerOpen);
|
||||
MinimizeCommand = new DelegateCommand<Window>(MinimizeWindow);
|
||||
MaximizeCommand = new DelegateCommand<Window>(MaximizeWindow);
|
||||
@@ -65,6 +67,9 @@ namespace LAEPS.ViewModels
|
||||
private void Load()
|
||||
{
|
||||
_notificationManager.ShowAsync(new NotificationContent { Title = "登录成功", Message = "", Type = NotificationType.Success });
|
||||
//默认导航到主界面
|
||||
Type moduleAType = typeof(MainModule.MainModule);
|
||||
_moduleManager.LoadModule(moduleAType.Name);
|
||||
}
|
||||
private void Navigate(string content)
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace MainModule
|
||||
public void RegisterTypes(IContainerRegistry containerRegistry)
|
||||
{
|
||||
containerRegistry.RegisterForNavigation<MainView>("MainView");
|
||||
containerRegistry.RegisterForNavigation<PostDetailView>("PostDetailView");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Model\Model.csproj" />
|
||||
<ProjectReference Include="..\Service\Service.csproj" />
|
||||
<ProjectReference Include="..\UIShare\UIShare.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,32 +1,155 @@
|
||||
using UIShare.ViewModelBase;
|
||||
using Model.Entity;
|
||||
using Prism.Commands;
|
||||
using Prism.Ioc;
|
||||
using Service.Interface;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows.Input;
|
||||
using UIShare.ViewModelBase;
|
||||
|
||||
namespace MainModule.ViewModels
|
||||
{
|
||||
public class MainViewModel : NavigateViewModelBase
|
||||
{
|
||||
#region 属性
|
||||
|
||||
|
||||
#endregion
|
||||
#region 命令
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
public MainViewModel(IContainerProvider containerProvider) : base(containerProvider)
|
||||
private ObservableCollection<PostEntity> _posts;
|
||||
public ObservableCollection<PostEntity> Posts
|
||||
{
|
||||
|
||||
get => _posts;
|
||||
set => SetProperty(ref _posts, value);
|
||||
}
|
||||
|
||||
|
||||
private string _searchKeyword;
|
||||
public string SearchKeyword
|
||||
{
|
||||
get => _searchKeyword;
|
||||
set => SetProperty(ref _searchKeyword, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 命令
|
||||
|
||||
public ICommand CreatePostCommand { get; set; }
|
||||
public ICommand SearchCommand { get; set; }
|
||||
public ICommand CategorySelectCommand { get; set; }
|
||||
|
||||
#endregion
|
||||
#region 私有字段
|
||||
private IContainerProvider _containerProvider;
|
||||
private IPostService _postService;
|
||||
private IDialogService _dialogService;
|
||||
#endregion
|
||||
public MainViewModel(IContainerProvider containerProvider ) : base(containerProvider)
|
||||
{
|
||||
_containerProvider=containerProvider;
|
||||
_postService = containerProvider.Resolve<IPostService>();
|
||||
_dialogService = containerProvider.Resolve<IDialogService>();
|
||||
InitializeCommands();
|
||||
LoadPosts();
|
||||
}
|
||||
|
||||
private void InitializeCommands()
|
||||
{
|
||||
CreatePostCommand = new DelegateCommand(OnCreatePost);
|
||||
SearchCommand = new AsyncDelegateCommand(OnSearch);
|
||||
CategorySelectCommand = new AsyncDelegateCommand<string>(OnCategorySelect);
|
||||
}
|
||||
|
||||
#region 命令处理
|
||||
|
||||
private async void OnCreatePost()
|
||||
{
|
||||
// 这里可以导航到发帖页面
|
||||
ShowInfoMessageBox("跳转到发帖页面",null);
|
||||
}
|
||||
|
||||
private async Task OnSearch()
|
||||
{
|
||||
// 执行搜索逻辑
|
||||
if (!string.IsNullOrWhiteSpace(SearchKeyword))
|
||||
{
|
||||
await SearchPostsAsync(SearchKeyword);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnCategorySelect(string category)
|
||||
{
|
||||
// 按分类筛选帖子
|
||||
await FilterPostsByCategoryAsync(category);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 业务方法
|
||||
|
||||
private async Task LoadPosts()
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await _postService.GetRecommendedPostsAsync(20);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
Posts = new ObservableCollection<PostEntity>(result.Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowErrorMessageBox("帖子加载错误",null);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowErrorMessageBox($"加载帖子异常: {ex.Message}", null);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SearchPostsAsync(string keyword)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await _postService.SearchPostsAsync(keyword);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
Posts = new ObservableCollection<PostEntity>(result.Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowErrorMessageBox("查询帖子失败", null);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 处理异常
|
||||
ShowErrorMessageBox($"查询帖子异常: {ex.Message}", null);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task FilterPostsByCategoryAsync(string category)
|
||||
{
|
||||
if (category == "全部")
|
||||
{
|
||||
await LoadPosts(); // 重新加载所有帖子
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var result = await _postService.GetPostsByCategoryAsync(category, 20);
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
Posts = new ObservableCollection<PostEntity>(result.Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowErrorMessageBox("加载分类子失败", null);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowErrorMessageBox($"获取分类帖子异常: {ex.Message}", null);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
138
MainModule/ViewModels/PostDetailViewModel.cs
Normal file
138
MainModule/ViewModels/PostDetailViewModel.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using Model.Entity;
|
||||
using Prism.Commands;
|
||||
using Prism.Ioc;
|
||||
using Service.Interface;
|
||||
using System.Windows.Input;
|
||||
using UIShare.ViewModelBase;
|
||||
|
||||
namespace MainModule.ViewModels
|
||||
{
|
||||
public class PostDetailViewModel : NavigateViewModelBase
|
||||
{
|
||||
#region 属性
|
||||
|
||||
private PostEntity _selectedPost;
|
||||
public PostEntity SelectedPost
|
||||
{
|
||||
get => _selectedPost;
|
||||
set => SetProperty(ref _selectedPost, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 命令
|
||||
|
||||
public ICommand LikePostCommand { get; set; }
|
||||
public ICommand FavoritePostCommand { get; set; }
|
||||
public ICommand SharePostCommand { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region 私有字段
|
||||
private IContainerProvider _containerProvider;
|
||||
private IPostService _postService;
|
||||
private IDialogService _dialogService;
|
||||
#endregion
|
||||
|
||||
public PostDetailViewModel(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_containerProvider = containerProvider;
|
||||
_postService = containerProvider.Resolve<IPostService>();
|
||||
_dialogService = containerProvider.Resolve<IDialogService>();
|
||||
InitializeCommands();
|
||||
}
|
||||
|
||||
private void InitializeCommands()
|
||||
{
|
||||
LikePostCommand = new DelegateCommand(OnLikePost);
|
||||
FavoritePostCommand = new DelegateCommand(OnFavoritePost);
|
||||
SharePostCommand = new DelegateCommand(OnSharePost);
|
||||
}
|
||||
|
||||
#region 命令处理
|
||||
|
||||
private async void OnLikePost()
|
||||
{
|
||||
if (SelectedPost != null)
|
||||
{
|
||||
SelectedPost.LikeCount++;
|
||||
// 在实际应用中,这里应该调用服务更新数据库
|
||||
var result = await _postService.UpdatePostAsync(SelectedPost);
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
var dialogParams = new DialogParameters();
|
||||
dialogParams.Add("Title", "错误");
|
||||
dialogParams.Add("Message", "点赞失败" + result.Msg);
|
||||
dialogParams.Add("Icon", "error");
|
||||
dialogParams.Add("ShowOk", true);
|
||||
_dialogService.ShowDialog("MessageBox", dialogParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnFavoritePost()
|
||||
{
|
||||
if (SelectedPost != null)
|
||||
{
|
||||
var dialogParams = new DialogParameters();
|
||||
dialogParams.Add("Title", "提示");
|
||||
dialogParams.Add("Message", "帖子已收藏");
|
||||
dialogParams.Add("Icon", "info");
|
||||
dialogParams.Add("ShowOk", true);
|
||||
_dialogService.ShowDialog("MessageBox", dialogParams, result =>
|
||||
{
|
||||
if (result.Result == ButtonResult.OK)
|
||||
{
|
||||
// 用户点击了确定
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnSharePost()
|
||||
{
|
||||
if (SelectedPost != null)
|
||||
{
|
||||
var dialogParams = new DialogParameters();
|
||||
dialogParams.Add("Title", "提示");
|
||||
dialogParams.Add("Message", "分享功能待实现");
|
||||
dialogParams.Add("Icon", "info");
|
||||
dialogParams.Add("ShowOk", true);
|
||||
_dialogService.ShowDialog("MessageBox", dialogParams, result =>
|
||||
{
|
||||
if (result.Result == ButtonResult.OK)
|
||||
{
|
||||
// 用户点击了确定
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 业务方法
|
||||
|
||||
public async void LoadPostDetails(PostEntity post)
|
||||
{
|
||||
if (post != null)
|
||||
{
|
||||
SelectedPost = post;
|
||||
// 增加浏览量
|
||||
SelectedPost.ViewCount++;
|
||||
// 在实际应用中,这里应该调用服务更新数据库
|
||||
var result = await _postService.UpdatePostAsync(SelectedPost);
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
var dialogParams = new DialogParameters();
|
||||
dialogParams.Add("Title", "错误");
|
||||
dialogParams.Add("Message", "加载帖子详情失败" + result.Msg);
|
||||
dialogParams.Add("Icon", "error");
|
||||
dialogParams.Add("ShowOk", true);
|
||||
_dialogService.ShowDialog("MessageBox", dialogParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,219 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:converters="clr-namespace:UIShare.Converters;assembly=UIShare"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
d:DesignHeight="1080"
|
||||
d:DesignWidth="1920">
|
||||
<Grid Background="Red">
|
||||
|
||||
<UserControl.Resources>
|
||||
<converters:BooleanToVisibilityConverter x:Key="BoolToVis" />
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<!-- 搜索栏区域 -->
|
||||
<RowDefinition Height="Auto"/>
|
||||
<!-- 标签分类区域 -->
|
||||
<RowDefinition Height="Auto"/>
|
||||
<!-- 内容区域 -->
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 顶部搜索栏 -->
|
||||
<Border Grid.Row="0" Background="#F5F5F5" Padding="20,15">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 搜索框 -->
|
||||
<TextBox Grid.Column="0"
|
||||
Margin="0,0,10,0"
|
||||
Style="{StaticResource MaterialDesignOutlinedTextBox}"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
Height="40"
|
||||
materialDesign:HintAssist.Hint="搜索帖子..."
|
||||
Text="{Binding SearchKeyword, UpdateSourceTrigger=PropertyChanged}"
|
||||
KeyDown="SearchBox_KeyDown"/>
|
||||
|
||||
<!-- 消息通知按钮 -->
|
||||
<Button Grid.Column="1"
|
||||
Margin="0,0,10,0"
|
||||
Style="{StaticResource MaterialDesignFloatingActionMiniDarkButton}"
|
||||
ToolTip="消息通知">
|
||||
<materialDesign:PackIcon Kind="BellOutline" Height="24" Width="24" />
|
||||
</Button>
|
||||
|
||||
<!-- 发帖按钮 -->
|
||||
<Button Grid.Column="2"
|
||||
Content="发布帖子"
|
||||
Style="{StaticResource MaterialDesignRaisedLightButton}"
|
||||
Background="#FF2196F3"
|
||||
Foreground="White"
|
||||
FontSize="14"
|
||||
FontWeight="Medium"
|
||||
Height="40"
|
||||
Width="100"
|
||||
Command="{Binding CreatePostCommand}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- 标签分类区域 -->
|
||||
<Border Grid.Row="1" Background="White" Padding="20,10" BorderBrush="#E0E0E0" BorderThickness="0,0,0,1">
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
|
||||
<StackPanel Orientation="Horizontal" >
|
||||
<Button Content="全部"
|
||||
Style="{StaticResource MaterialDesignFlatButton}"
|
||||
Background="#FF2196F3"
|
||||
Foreground="White"
|
||||
Command="{Binding CategorySelectCommand}"
|
||||
CommandParameter="全部"/>
|
||||
<Button Content="热门"
|
||||
Style="{StaticResource MaterialDesignFlatButton}"
|
||||
Background="#FF9800"
|
||||
Foreground="White"
|
||||
Command="{Binding CategorySelectCommand}"
|
||||
CommandParameter="热门"/>
|
||||
<Button Content="科技"
|
||||
Style="{StaticResource MaterialDesignFlatButton}"
|
||||
Background="#4CAF50"
|
||||
Foreground="White"
|
||||
Command="{Binding CategorySelectCommand}"
|
||||
CommandParameter="科技"/>
|
||||
<Button Content="生活"
|
||||
Style="{StaticResource MaterialDesignFlatButton}"
|
||||
Background="#9C27B0"
|
||||
Foreground="White"
|
||||
Command="{Binding CategorySelectCommand}"
|
||||
CommandParameter="生活"/>
|
||||
<Button Content="娱乐"
|
||||
Style="{StaticResource MaterialDesignFlatButton}"
|
||||
Background="#E91E63"
|
||||
Foreground="White"
|
||||
Command="{Binding CategorySelectCommand}"
|
||||
CommandParameter="娱乐"/>
|
||||
<Button Content="游戏"
|
||||
Style="{StaticResource MaterialDesignFlatButton}"
|
||||
Background="#795548"
|
||||
Foreground="White"
|
||||
Command="{Binding CategorySelectCommand}"
|
||||
CommandParameter="游戏"/>
|
||||
<Button Content="学习"
|
||||
Style="{StaticResource MaterialDesignFlatButton}"
|
||||
Background="#009688"
|
||||
Foreground="White"
|
||||
Command="{Binding CategorySelectCommand}"
|
||||
CommandParameter="学习"/>
|
||||
<Button Content="美食"
|
||||
Style="{StaticResource MaterialDesignFlatButton}"
|
||||
Background="#FF5722"
|
||||
Foreground="White"
|
||||
Command="{Binding CategorySelectCommand}"
|
||||
CommandParameter="美食"/>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
|
||||
<!-- 推荐帖子列表 -->
|
||||
<ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto">
|
||||
<ItemsControl ItemsSource="{Binding Posts}" Margin="20,15,20,20">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Background="White"
|
||||
Margin="0,0,0,15"
|
||||
CornerRadius="8"
|
||||
BorderBrush="#E0E0E0"
|
||||
BorderThickness="1"
|
||||
Effect="{DynamicResource MaterialDesignShadowDepth1}">
|
||||
<Grid Margin="15">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 帖子头部信息 -->
|
||||
<Grid Grid.Row="0" Margin="0,0,0,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 用户头像占位 -->
|
||||
<Ellipse Grid.Column="0"
|
||||
Width="40"
|
||||
Height="40"
|
||||
Fill="#BDBDBD"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<StackPanel Grid.Column="1" Margin="10,0,0,0" VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding AuthorName}"
|
||||
FontSize="14"
|
||||
FontWeight="Medium"
|
||||
Foreground="#212121"/>
|
||||
<TextBlock Text="{Binding PublishTime, StringFormat=\{0:MM-dd HH:mm\}}"
|
||||
FontSize="12"
|
||||
Foreground="#757575"
|
||||
Margin="0,2,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 置顶或精华标识 -->
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" HorizontalAlignment="Right" >
|
||||
<Border Background="#FF9800" Padding="6,2" CornerRadius="3" Visibility="{Binding IsEssence, Converter={StaticResource BoolToVis}}">
|
||||
<TextBlock Text="精" FontSize="12" Foreground="White" FontWeight="Bold"/>
|
||||
</Border>
|
||||
<Border Background="#2196F3" Padding="6,2" CornerRadius="3" Visibility="{Binding IsTop, Converter={StaticResource BoolToVis}}">
|
||||
<TextBlock Text="顶" FontSize="12" Foreground="White" FontWeight="Bold"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- 帖子标题和内容 -->
|
||||
<StackPanel Grid.Row="1" Margin="0,0,0,10">
|
||||
<TextBlock Text="{Binding Title}"
|
||||
FontSize="16"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#212121"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,0,0,5"/>
|
||||
<TextBlock Text="{Binding Content}"
|
||||
FontSize="14"
|
||||
Foreground="#424242"
|
||||
TextWrapping="Wrap"
|
||||
MaxHeight="60"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 帖子底部统计信息 -->
|
||||
<Grid Grid.Row="2">
|
||||
<StackPanel Orientation="Horizontal" >
|
||||
<StackPanel Orientation="Horizontal" >
|
||||
<materialDesign:PackIcon Kind="Eye" Height="16" Width="16" Foreground="#757575"/>
|
||||
<TextBlock Text="{Binding ViewCount}" Foreground="#757575" FontSize="12"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Kind="ThumbUpOutline" Height="16" Width="16" Foreground="#757575"/>
|
||||
<TextBlock Text="{Binding LikeCount}" Foreground="#757575" FontSize="12"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Kind="CommentOutline" Height="16" Width="16" Foreground="#757575"/>
|
||||
<TextBlock Text="{Binding CommentCount}" Foreground="#757575" FontSize="12"/>
|
||||
</StackPanel>
|
||||
<TextBlock Text="{Binding Category}" Foreground="#2196F3" FontSize="12" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -25,6 +25,16 @@ namespace MainModule.Views
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
private void SearchBox_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
// 触发搜索命令
|
||||
if (DataContext is ViewModels.MainViewModel viewModel)
|
||||
{
|
||||
viewModel.SearchCommand?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
108
MainModule/Views/PostDetailView.xaml
Normal file
108
MainModule/Views/PostDetailView.xaml
Normal file
@@ -0,0 +1,108 @@
|
||||
<UserControl x:Class="MainModule.Views.PostDetailView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:converters="clr-namespace:UIShare.Converters;assembly=UIShare"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
d:DesignHeight="800"
|
||||
d:DesignWidth="1000">
|
||||
<UserControl.Resources>
|
||||
<converters:BooleanToVisibilityConverter x:Key="BoolToVis" />
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Margin="20">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 帖子头部信息 -->
|
||||
<Border Grid.Row="0" Background="White" CornerRadius="8" BorderBrush="#E0E0E0" BorderThickness="1" Padding="20">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Ellipse Grid.Column="0" Width="50" Height="50" Fill="#BDBDBD" VerticalAlignment="Center"/>
|
||||
|
||||
<StackPanel Grid.Column="1" Margin="15,0,0,0" VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding SelectedPost.AuthorName}" FontSize="16" FontWeight="Medium" Foreground="#212121"/>
|
||||
<TextBlock Text="{Binding SelectedPost.PublishTime, StringFormat=\\{0:yyyy-MM-dd HH:mm:ss\\}}" FontSize="12" Foreground="#757575" Margin="0,2,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" HorizontalAlignment="Right" >
|
||||
<Border Background="#FF9800" Padding="8,4" CornerRadius="4" Visibility="{Binding SelectedPost.IsEssence, Converter={StaticResource BoolToVis}}">
|
||||
<TextBlock Text="精" FontSize="12" Foreground="White" FontWeight="Bold"/>
|
||||
</Border>
|
||||
<Border Background="#2196F3" Padding="8,4" CornerRadius="4" Visibility="{Binding SelectedPost.IsTop, Converter={StaticResource BoolToVis}}">
|
||||
<TextBlock Text="顶" FontSize="12" Foreground="White" FontWeight="Bold"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- 帖子内容区域 -->
|
||||
<Border Grid.Row="1" Background="White" CornerRadius="8" BorderBrush="#E0E0E0" BorderThickness="1" Margin="0,10,0,10" Padding="20">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{Binding SelectedPost.Title}" FontSize="24" FontWeight="Bold" Foreground="#212121" Margin="0,0,0,20"/>
|
||||
<TextBlock Text="{Binding SelectedPost.Content}" FontSize="16" Foreground="#424242" TextWrapping="Wrap" LineHeight="28"/>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
|
||||
<!-- 统计信息和操作区域 -->
|
||||
<Border Grid.Row="2" Background="White" CornerRadius="8" BorderBrush="#E0E0E0" BorderThickness="1" Padding="20">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel Grid.Column="0" Orientation="Horizontal" >
|
||||
<StackPanel Orientation="Horizontal" >
|
||||
<materialDesign:PackIcon Kind="Eye" Height="20" Width="20" Foreground="#757575"/>
|
||||
<TextBlock Text="{Binding SelectedPost.ViewCount}" Foreground="#757575" FontSize="14"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal" >
|
||||
<materialDesign:PackIcon Kind="ThumbUpOutline" Height="20" Width="20" Foreground="#757575"/>
|
||||
<TextBlock Text="{Binding SelectedPost.LikeCount}" Foreground="#757575" FontSize="14"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal" >
|
||||
<materialDesign:PackIcon Kind="CommentOutline" Height="20" Width="20" Foreground="#757575"/>
|
||||
<TextBlock Text="{Binding SelectedPost.CommentCount}" Foreground="#757575" FontSize="14"/>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Text="{Binding SelectedPost.Category}" Foreground="#2196F3" FontSize="14" FontWeight="Medium" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
||||
<Button Content="点赞"
|
||||
Style="{StaticResource MaterialDesignRaisedLightButton}"
|
||||
Background="#4CAF50"
|
||||
Foreground="White"
|
||||
Command="{Binding LikePostCommand}"/>
|
||||
<Button Content="收藏"
|
||||
Style="{StaticResource MaterialDesignRaisedLightButton}"
|
||||
Background="#FF9800"
|
||||
Foreground="White"
|
||||
Command="{Binding FavoritePostCommand}"/>
|
||||
<Button Content="分享"
|
||||
Style="{StaticResource MaterialDesignRaisedLightButton}"
|
||||
Background="#2196F3"
|
||||
Foreground="White"
|
||||
Command="{Binding SharePostCommand}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
28
MainModule/Views/PostDetailView.xaml.cs
Normal file
28
MainModule/Views/PostDetailView.xaml.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace MainModule.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// PostDetailView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class PostDetailView : UserControl
|
||||
{
|
||||
public PostDetailView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Model/Entity/PostEntity.cs
Normal file
24
Model/Entity/PostEntity.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Model.Entity
|
||||
{
|
||||
public class PostEntity : BaseEntity
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string Content { get; set; }
|
||||
public string AuthorId { get; set; }
|
||||
public string AuthorName { get; set; }
|
||||
public string Category { get; set; }
|
||||
public DateTime PublishTime { get; set; }
|
||||
public int ViewCount { get; set; }
|
||||
public int LikeCount { get; set; }
|
||||
public int CommentCount { get; set; }
|
||||
public bool IsTop { get; set; }
|
||||
public bool IsEssence { get; set; }
|
||||
public string ThumbnailUrl { get; set; }
|
||||
}
|
||||
}
|
||||
129
Service/Implement/PostService.cs
Normal file
129
Service/Implement/PostService.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
using Model;
|
||||
using Model.Entity;
|
||||
using ORM;
|
||||
using Service.Implement;
|
||||
using Service.Interface;
|
||||
using SqlSugar;
|
||||
|
||||
namespace Service.Implement
|
||||
{
|
||||
public class PostService : BaseService<PostEntity>, IPostService
|
||||
{
|
||||
public PostService(SqlSugarRepository<PostEntity> repository) : base(repository)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<Result<List<PostEntity>>> GetRecommendedPostsAsync(int count = 10)
|
||||
{
|
||||
try
|
||||
{
|
||||
var posts = await _repository.Entities
|
||||
.Where(x => x.IsDel == 0) // 使用正确的字段名
|
||||
.OrderBy(x => x.IsTop, OrderByType.Desc)
|
||||
.OrderBy(x => x.PublishTime, OrderByType.Desc)
|
||||
.Take(count)
|
||||
.ToListAsync();
|
||||
|
||||
return Result<List<PostEntity>>.Success(posts);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result<List<PostEntity>>.Error("获取推荐帖子失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result<List<PostEntity>>> SearchPostsAsync(string keyword)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(keyword))
|
||||
{
|
||||
return Result<List<PostEntity>>.Success(new List<PostEntity>());
|
||||
}
|
||||
|
||||
var posts = await _repository.Entities
|
||||
.Where(x => (x.Title.Contains(keyword) || x.Content.Contains(keyword))
|
||||
&& x.IsDel == 0) // 使用正确的字段名
|
||||
.OrderBy(x => x.IsTop, OrderByType.Desc)
|
||||
.OrderBy(x => x.PublishTime, OrderByType.Desc)
|
||||
.ToListAsync();
|
||||
|
||||
return Result<List<PostEntity>>.Success(posts);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result<List<PostEntity>>.Error("搜索帖子失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result<List<PostEntity>>> GetPostsByCategoryAsync(string category, int count = 10)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(category))
|
||||
{
|
||||
return Result<List<PostEntity>>.Success(new List<PostEntity>());
|
||||
}
|
||||
|
||||
var posts = await _repository.Entities
|
||||
.Where(x => x.Category == category && x.IsDel == 0) // 使用正确的字段名
|
||||
.OrderBy(x => x.IsTop, OrderByType.Desc)
|
||||
.OrderBy(x => x.PublishTime, OrderByType.Desc)
|
||||
.Take(count)
|
||||
.ToListAsync();
|
||||
|
||||
return Result<List<PostEntity>>.Success(posts);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result<List<PostEntity>>.Error("获取分类帖子失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result<bool>> CreatePostAsync(PostEntity post)
|
||||
{
|
||||
try
|
||||
{
|
||||
post.PublishTime = DateTime.Now;
|
||||
var result = await _repository.InsertAsync(post);
|
||||
return Result<bool>.Success(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result<bool>.Error("创建帖子失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result<bool>> UpdatePostAsync(PostEntity post)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await _repository.UpdateAsync(post);
|
||||
return Result<bool>.Success(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result<bool>.Error("更新帖子失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Result<bool>> DeletePostAsync(long postId)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 软删除:将IsDel设为1
|
||||
var post = await _repository.Entities.FirstAsync(x => x.Id == postId);
|
||||
if (post == null)
|
||||
return Result<bool>.Error("帖子不存在");
|
||||
|
||||
post.IsDel = 1;
|
||||
var result = await _repository.UpdateAsync(post);
|
||||
return Result<bool>.Success(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result<bool>.Error("删除帖子失败", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,9 @@
|
||||
using Model.Entity;
|
||||
using ORM;
|
||||
using Service.Implement;
|
||||
using Service.Interface;
|
||||
|
||||
public class UserService: BaseService<UserEntity>
|
||||
public class UserService: BaseService<UserEntity>, IUserService
|
||||
{
|
||||
public UserService(SqlSugarRepository<UserEntity> repository) : base(repository)
|
||||
{
|
||||
|
||||
16
Service/Interface/IPostService.cs
Normal file
16
Service/Interface/IPostService.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Model;
|
||||
using Model.Entity;
|
||||
using Service.Interface;
|
||||
|
||||
namespace Service.Interface
|
||||
{
|
||||
public interface IPostService : IBaseService<PostEntity>
|
||||
{
|
||||
Task<Result<List<PostEntity>>> GetRecommendedPostsAsync(int count = 10);
|
||||
Task<Result<List<PostEntity>>> SearchPostsAsync(string keyword);
|
||||
Task<Result<List<PostEntity>>> GetPostsByCategoryAsync(string category, int count = 10);
|
||||
Task<Result<bool>> CreatePostAsync(PostEntity post);
|
||||
Task<Result<bool>> UpdatePostAsync(PostEntity post);
|
||||
Task<Result<bool>> DeletePostAsync(long postId);
|
||||
}
|
||||
}
|
||||
11
Service/Interface/IUserService.cs
Normal file
11
Service/Interface/IUserService.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Model;
|
||||
using Model.Entity;
|
||||
|
||||
namespace Service.Interface
|
||||
{
|
||||
public interface IUserService : IBaseService<UserEntity>
|
||||
{
|
||||
public Task<Result<UserEntity>> GetUserByUserNameAsync(string username);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,6 +22,30 @@ namespace UIShare.ViewModelBase
|
||||
_notificationManager = containerProvider.Resolve<INotificationManager>();
|
||||
}
|
||||
|
||||
protected void ShowInfoMessageBox(string Message,Action callback)
|
||||
{
|
||||
var dialogParams = new DialogParameters();
|
||||
dialogParams.Add("Title", "提示");
|
||||
dialogParams.Add("Message", Message);
|
||||
dialogParams.Add("Icon", "info");
|
||||
dialogParams.Add("ShowOk", true);
|
||||
_dialogService.ShowDialog("MessageBoxView", dialogParams, result =>
|
||||
{
|
||||
callback();
|
||||
});
|
||||
}
|
||||
protected void ShowErrorMessageBox(string Message,Action callback)
|
||||
{
|
||||
var dialogParams = new DialogParameters();
|
||||
dialogParams.Add("Title", "错误");
|
||||
dialogParams.Add("Message", Message);
|
||||
dialogParams.Add("Icon", "info");
|
||||
dialogParams.Add("ShowOk", true);
|
||||
_dialogService.ShowDialog("MessageBoxView", dialogParams, result =>
|
||||
{
|
||||
callback();
|
||||
});
|
||||
}
|
||||
#region Navigation
|
||||
|
||||
public virtual void OnNavigatedTo(NavigationContext navigationContext) { }
|
||||
|
||||
Reference in New Issue
Block a user