173 lines
5.9 KiB
C#
173 lines
5.9 KiB
C#
|
|
using LiveChartsCore;
|
|||
|
|
using LiveChartsCore.Drawing;
|
|||
|
|
using LiveChartsCore.Kernel;
|
|||
|
|
using System.Collections.ObjectModel;
|
|||
|
|
using System.Windows.Input;
|
|||
|
|
using YY.Admin.Core;
|
|||
|
|
using YY.Admin.Services.Service.User;
|
|||
|
|
|
|||
|
|
namespace YY.Admin.ViewModels
|
|||
|
|
{
|
|||
|
|
public class StatisticCard
|
|||
|
|
{
|
|||
|
|
public string Title { get; set; } = string.Empty;
|
|||
|
|
public string Value { get; set; } = string.Empty;
|
|||
|
|
public string Icon { get; set; } = string.Empty;
|
|||
|
|
public string Color { get; set; } = string.Empty;
|
|||
|
|
public string Trend { get; set; } = string.Empty;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public class RecentActivity
|
|||
|
|
{
|
|||
|
|
public string Title { get; set; } = string.Empty;
|
|||
|
|
public string Description { get; set; } = string.Empty;
|
|||
|
|
public DateTime Time { get; set; }
|
|||
|
|
public string Icon { get; set; } = string.Empty;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public class DashboardViewModel : BaseViewModel
|
|||
|
|
{
|
|||
|
|
private readonly ISysUserService _userService;
|
|||
|
|
|
|||
|
|
public float[] Values1 { get; set; } = FetchVales(0);
|
|||
|
|
public float[] Values2 { get; set; } = FetchVales(-0.15f);
|
|||
|
|
|
|||
|
|
public ICommand PointMeasuredCommand { get; }
|
|||
|
|
|
|||
|
|
public DashboardViewModel(
|
|||
|
|
ISysUserService userService,
|
|||
|
|
IContainerExtension _container,
|
|||
|
|
IRegionManager regionManager
|
|||
|
|
) : base(_container, regionManager)
|
|||
|
|
{
|
|||
|
|
// _eventAggregator.GetEvent<ThemeChangedEvent>().Subscribe(ApplyTheme);
|
|||
|
|
_userService = userService;
|
|||
|
|
|
|||
|
|
PointMeasuredCommand = new DelegateCommand<ChartPoint>(OnPointMeasured);
|
|||
|
|
|
|||
|
|
_ = LoadDashboardDataAsync();
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public ObservableCollection<StatisticCard> StatisticCards { get; } = new();
|
|||
|
|
public ObservableCollection<RecentActivity> RecentActivities { get; } = new();
|
|||
|
|
|
|||
|
|
private async Task LoadDashboardDataAsync()
|
|||
|
|
{
|
|||
|
|
IsLoading = true;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
// 加载统计数据
|
|||
|
|
var users = await _userService.GetUsersAsync();
|
|||
|
|
|
|||
|
|
StatisticCards.Clear();
|
|||
|
|
StatisticCards.Add(new StatisticCard
|
|||
|
|
{
|
|||
|
|
Title = "总用户数",
|
|||
|
|
Value = users.Count.ToString(),
|
|||
|
|
Icon = "UserOutlined",
|
|||
|
|
Color = "#1890ff",
|
|||
|
|
Trend = "+12%"
|
|||
|
|
});
|
|||
|
|
StatisticCards.Add(new StatisticCard
|
|||
|
|
{
|
|||
|
|
Title = "活跃用户",
|
|||
|
|
Value = users.Count(u => u.Status== StatusEnum.Enable).ToString(),
|
|||
|
|
Icon = "UserCheckOutlined",
|
|||
|
|
Color = "#52c41a",
|
|||
|
|
Trend = "+8%"
|
|||
|
|
});
|
|||
|
|
StatisticCards.Add(new StatisticCard
|
|||
|
|
{
|
|||
|
|
Title = "今日访问",
|
|||
|
|
Value = "1,234",
|
|||
|
|
Icon = "EyeOutlined",
|
|||
|
|
Color = "#faad14",
|
|||
|
|
Trend = "+5%"
|
|||
|
|
});
|
|||
|
|
StatisticCards.Add(new StatisticCard
|
|||
|
|
{
|
|||
|
|
Title = "系统消息",
|
|||
|
|
Value = "56",
|
|||
|
|
Icon = "MessageOutlined",
|
|||
|
|
Color = "#f5222d",
|
|||
|
|
Trend = "+2"
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 加载最近活动
|
|||
|
|
RecentActivities.Clear();
|
|||
|
|
RecentActivities.Add(new RecentActivity
|
|||
|
|
{
|
|||
|
|
Title = "用户登录",
|
|||
|
|
Description = "管理员 admin 登录系统",
|
|||
|
|
Time = DateTime.Now.AddMinutes(-5),
|
|||
|
|
Icon = "LoginOutlined"
|
|||
|
|
});
|
|||
|
|
RecentActivities.Add(new RecentActivity
|
|||
|
|
{
|
|||
|
|
Title = "数据更新",
|
|||
|
|
Description = "用户数据已同步更新",
|
|||
|
|
Time = DateTime.Now.AddMinutes(-15),
|
|||
|
|
Icon = "SyncOutlined"
|
|||
|
|
});
|
|||
|
|
RecentActivities.Add(new RecentActivity
|
|||
|
|
{
|
|||
|
|
Title = "系统备份",
|
|||
|
|
Description = "数据库备份已完成",
|
|||
|
|
Time = DateTime.Now.AddHours(-2),
|
|||
|
|
Icon = "DatabaseOutlined"
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
finally
|
|||
|
|
{
|
|||
|
|
IsLoading = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static float[] FetchVales(float offset)
|
|||
|
|
{
|
|||
|
|
var values = new List<float>();
|
|||
|
|
|
|||
|
|
// the EasingFunctions.BounceInOut, is just
|
|||
|
|
// a function that looks nice!
|
|||
|
|
|
|||
|
|
var fx = EasingFunctions.BounceInOut;
|
|||
|
|
var x = 0f;
|
|||
|
|
|
|||
|
|
while (x <= 1)
|
|||
|
|
{
|
|||
|
|
values.Add(fx(x + offset));
|
|||
|
|
x += 0.025f;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return [.. values];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void OnPointMeasured(ChartPoint point)
|
|||
|
|
{
|
|||
|
|
// each point will have a different delay depending on its index
|
|||
|
|
var index = point.Context.Entity.MetaData!.EntityIndex; // the index of the point in the data source
|
|||
|
|
var delay = index / (float)Values1.Length;
|
|||
|
|
|
|||
|
|
// the animation takes a function, that represents the normalized progress of the animation
|
|||
|
|
// the parameter is the normalized time of the animation, it goes from 0 to 1
|
|||
|
|
// the function must return a value from 0 to 1, where 0 is the initial state
|
|||
|
|
// and 1 is the final state
|
|||
|
|
var duration = TimeSpan.FromSeconds(3);
|
|||
|
|
var animation = new Animation(t => DelayedEase(t, delay), duration);
|
|||
|
|
|
|||
|
|
point.Context.Visual?.SetTransition(animation);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static float DelayedEase(float t, float delay)
|
|||
|
|
{
|
|||
|
|
if (t <= delay) return 0f;
|
|||
|
|
|
|||
|
|
var remappedT = (t - delay) / (1f - delay);
|
|||
|
|
var baseEasing = EasingFunctions.BuildCustomElasticOut(1.5f, 0.60f);
|
|||
|
|
return baseEasing(Math.Clamp(remappedT, 0f, 1f));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|