From 55e098c5a3f116363d02500b8d7df5989e533427 Mon Sep 17 00:00:00 2001 From: Alex Chow Date: Sun, 3 Apr 2022 22:55:37 +0200 Subject: [PATCH] b06chart_fsql --- b06chart/Components/ChartsBase.razor | 69 +++++ b06chart/Components/ChartsBase.razor.cs | 284 +++++++++++++++++++ b06chart/Model/OrdersEntry.cs | 97 +++++++ b06chart/Pages/DayReport.razor | 22 ++ b06chart/Pages/DayReport.razor.cs | 59 ++++ b06chart/Pages/OrdersTopSalesCharts.razor | 20 ++ b06chart/Pages/OrdersTopSalesCharts.razor.cs | 68 +++++ b06chart/Program.cs | 12 + b06chart/Shared/NavMenu.razor | 12 +- b06chart/_Imports.razor | 1 + b06chart/b06chart.csproj | 23 +- 11 files changed, 651 insertions(+), 16 deletions(-) create mode 100644 b06chart/Components/ChartsBase.razor create mode 100644 b06chart/Components/ChartsBase.razor.cs create mode 100644 b06chart/Model/OrdersEntry.cs create mode 100644 b06chart/Pages/DayReport.razor create mode 100644 b06chart/Pages/DayReport.razor.cs create mode 100644 b06chart/Pages/OrdersTopSalesCharts.razor create mode 100644 b06chart/Pages/OrdersTopSalesCharts.razor.cs diff --git a/b06chart/Components/ChartsBase.razor b/b06chart/Components/ChartsBase.razor new file mode 100644 index 0000000..bffa162 --- /dev/null +++ b/b06chart/Components/ChartsBase.razor @@ -0,0 +1,69 @@ +@namespace b06chart + +@if (!IsHideSelectores) +{ + @Year 年 + @Month 月 + + 合计 : @(Total.ToString("N2")) + @TotalString2 + @TotalString3 + +} + + +
+ @if (!IsHideSelectores && UseDateTimeRangeValue) + { + + } +
+ @if (!IsHideSelectores) + { + for (int i = DateTime.Now.Year - 7; i <= DateTime.Now.Year; i++) + { + var year = i; + + + +
+
+ +@if (!IsHideSelectores && IsShowMonthSelector) +{ +
+
+ @{ + for (int i = 1; i <= 12; i++) + { + var month = i; + + + +
+
+} + +
+ @if (Show) + { + if (!IsLineChart) + { + + } + else + { + + } + } +
+ + \ No newline at end of file diff --git a/b06chart/Components/ChartsBase.razor.cs b/b06chart/Components/ChartsBase.razor.cs new file mode 100644 index 0000000..6c7e57c --- /dev/null +++ b/b06chart/Components/ChartsBase.razor.cs @@ -0,0 +1,284 @@ +using BootstrapBlazor.Components; +using Microsoft.AspNetCore.Components; +using System.Diagnostics.CodeAnalysis; + +namespace b06chart +{ + public partial class ChartsBase + { + [NotNull] private Chart? LineChart { get; set; } + [NotNull] private Chart? BarChart { get; set; } + + /// + /// 设定当前年份 + /// + [Parameter] public int Year { get; set; } = DateTime.Now.Year; + + /// + /// 设定当前月份 + /// + [Parameter] public int Month { get; set; } = DateTime.Now.Month; + + /// + /// 设定图表抬头 + /// + [Parameter] public string TitleCharts { get; set; } = "日报表"; + + /// + /// 设定X轴文本 + /// + [Parameter] public string XAxesText { get; set; } = "天数"; + + /// + /// 设定Y轴文本 + /// + [Parameter] public string YAxesText { get; set; } = "数值"; + + /// + /// 图表类型:是=LineChart,否=BarChart + /// + [Parameter] public bool IsLineChart { get; set; } + + /// + /// 使用默认数据 + /// + [Parameter] public bool IsDemo { get; set; } + + /// + /// 显示月份选择器 + /// + [Parameter] public bool IsShowMonthSelector { get; set; } = true; + [Parameter] public EventCallback OnInitCallback { get; set; } + [Parameter] public EventCallback 数据生成Callback { get; set; } + [Parameter] public decimal Total { get; set; } + [Parameter] public string? TotalString2 { get; set; } + [Parameter] public string? TotalString3 { get; set; } + + /// + /// 隐藏选择器 + /// + [Parameter] public bool IsHideSelectores { get; set; } + + /// + /// 使用/初始化日期选择控件日期 + /// + [Parameter] public bool UseDateTimeRangeValue { get; set; } + + /// + /// 是否合并Bar显示 默认false + /// + public bool IsStacked { get; set; } + + /// + /// 强刷显示控件控制,Hack一下 + /// + private bool Show { get; set; } = true; + public int LastCount { get; set; } + public bool FirstLoad { get; set; } = true; + public bool ForceRefresh { get; set; } + private string? ClickItemID { get; set; } + + private IEnumerable Colors { get; set; } = new List() { "Blue", "Green", "Red", "Orange", "Yellow", "Tomato", "Pink", "Violet" }; + + #region 日期选择控件 + private DateTimeRangeValue DateTimeRangeValue1 { get; set; } = new DateTimeRangeValue(); + DateTime 起始日期 = DateTime.Today.FirstDay(); + DateTime 结束日期 = DateTime.Today.LastDay(); + private Task OnConfirm(DateTimeRangeValue value) + { + 起始日期 = value.Start.FirstSecond(); + 结束日期 = value.End.Year == 1 ? value.Start.LastSecond() : value.End.LastSecond(); + + Chart chart = IsLineChart ? LineChart : BarChart; + chart?.Update(ChartAction.Update); + //StateHasChanged(); + return Task.CompletedTask; + } + private Task OnClear(DateTimeRangeValue value) + { + 起始日期 = DateTime.Today.FirstDay(); + 结束日期 = DateTime.Today.LastDay(); + Chart chart = IsLineChart ? LineChart : BarChart; + chart?.Update(ChartAction.Update); + //StateHasChanged(); + return Task.CompletedTask; + } + + /// + /// 设置日期选择控件日期 + /// + /// + /// + /// + protected Task SetDates(DateTime _起始日期, DateTime _结束日期) + { + 起始日期 = _起始日期; + 结束日期 = _结束日期; + DateTimeRangeValue1.Start = 起始日期; + DateTimeRangeValue1.End = 结束日期; + return Task.CompletedTask; + } + #endregion + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + + if (UseDateTimeRangeValue && firstRender) { + DateTimeRangeValue1.Start = 起始日期; + DateTimeRangeValue1.End = 结束日期; + } + } + private Task OnAfterInit() + { + System.Console.WriteLine("Bar 初始化完毕"); + return Task.CompletedTask; + } + + /// + /// 初始化 ChartDataSource + /// + /// + protected Task OnInit() + { + var ds = new ChartDataSource(); + if (!OnInitCallback.HasDelegate) + { + ds.Options.Title = TitleCharts; + ds.Options.X.Title = XAxesText; + ds.Options.X.Stacked = IsStacked; + ds.Options.Y.Title = YAxesText; + ds.Options.Y.Stacked = IsStacked; + } + else + { + OnInitCallback.InvokeAsync(ds); + } + + + //设置自定义颜色 + ds.Options.Colors = new Dictionary() { + { "blue:", "rgb(54, 162, 235)" }, + { "green:", "rgb(75, 192, 192)" }, + { "red:", "rgb(255, 99, 132)" }, + { "orange:", "rgb(255, 159, 64)" }, + { "yellow:", "rgb(255, 205, 86)" }, + { "tomato:", "rgb(255, 99, 71)" }, + { "pink:", "rgb(255, 192, 203)" }, + { "violet:", "rgb(238, 130, 238)" }, + }; + + if (!数据生成Callback.HasDelegate) + 数据生成(ds); + else + 数据生成Callback.InvokeAsync(ds); + + ForceRefresh = LastCount < (ds.Labels?.Count()??0); + LastCount = ds.Labels?.Count()??0; + + if (!FirstLoad && ForceRefresh) + { + ReloadChart(); + ForceRefresh = false; + } + FirstLoad = false; + + return Task.FromResult(ds); + } + + + /// + /// 数据生成,添加Labels和ChartDataset + /// + /// + protected virtual void 数据生成(ChartDataSource ds) + { + } + + private Task SetYear(int year) + { + Chart chart = IsLineChart ? LineChart : BarChart; + Year = year; + chart?.Update(ChartAction.Update); + return Task.CompletedTask; + } + private Task SetMonth(int month) + { + Chart chart = IsLineChart ? LineChart : BarChart; + Month = month; + chart?.Update(ChartAction.Update); + return Task.CompletedTask; + } + private Task PreMonth() + { + Chart chart = IsLineChart ? LineChart : BarChart; + Year = Month - 1 >= 1 ? Year : Year - 1; + Month = Month - 1 >= 1 ? Month - 1 : 12; + chart?.Update(ChartAction.Update); + return Task.CompletedTask; + } + private Task NextMonth() + { + Chart chart = IsLineChart ? LineChart : BarChart; + Year = Month + 1 <= 12 ? Year : Year + 1; + Month = Month + 1 <= 12 ? Month + 1 : 1; + chart?.Update(ChartAction.Update); + return Task.CompletedTask; + } + private Task SetNow() + { + Chart chart = IsLineChart ? LineChart : BarChart; + Year = DateTime.Now.Year; + Month = DateTime.Now.Month; + chart?.Update(ChartAction.Update); + return Task.CompletedTask; + } + + private Task RandomData() + { + Chart chart = IsLineChart ? LineChart : BarChart; + chart?.Update(ChartAction.Update); + return Task.CompletedTask; + } + private Task SwitchChart() + { + IsLineChart = !IsLineChart; + return Task.CompletedTask; + } + + /// + /// 切换合并显示 + /// + private void SwitchStacked() + { + IsStacked = !IsStacked; + ReloadChart(); + } + + /// + /// 强刷控件,重新初始化控件外观 + /// + private async void ReloadChart(bool reloadData=false) + { + Chart chart = IsLineChart ? LineChart : BarChart; + if (reloadData) chart?.Update(ChartAction.Update); + Show = false; + await InvokeAsync(StateHasChanged); + await Task.Delay(1); + Show = true; + await InvokeAsync(StateHasChanged); + } + + + } + + + public static class DateTimeExtensions + { + public static DateTime FirstDay(this DateTime obj) => new DateTime(obj.Year, obj.Month, 1, 0, 0, 0); + public static DateTime LastDay(this DateTime obj) => obj.FirstDay().AddMonths(1).AddDays(-1).LastSecond(); + public static DateTime FirstSecond(this DateTime obj) => new DateTime(obj.Year, obj.Month, obj.Day, 0, 0, 0); + public static DateTime LastSecond(this DateTime obj) => new DateTime(obj.Year, obj.Month, obj.Day, 23, 59, 59); + + } +} diff --git a/b06chart/Model/OrdersEntry.cs b/b06chart/Model/OrdersEntry.cs new file mode 100644 index 0000000..f7ddc5b --- /dev/null +++ b/b06chart/Model/OrdersEntry.cs @@ -0,0 +1,97 @@ +using BootstrapBlazor.Components; +using FreeSql.DataAnnotations; +using Newtonsoft.Json; +using System.ComponentModel; +using System.Linq; + +namespace Blazor100.Data; + + +public partial class Orders +{ + /// + /// 流水号 + /// + + [AutoGenerateColumn(Editable = false, DefaultSort = true, DefaultSortOrder = SortOrder.Desc, Order = 1)] + [JsonProperty, Column(IsIdentity = true)] + [DisplayName("流水号")] + public int OrderID { get; set; } + + /// + /// 单据日期 + /// + [AutoGenerateColumn(FormatString = "yyyy-MM-dd", ComponentType = typeof(DatePickerBody))] + [JsonProperty] + [DisplayName("日期")] + public DateTime OrderDate { get; set; } + + /// + /// 合计金额 + /// + [AutoGenerateColumn(FormatString = "N2", Align = Alignment.Right)] + [JsonProperty, Column(DbType = "decimal(19,4)")] + [DisplayName("合计")] + public decimal SubTotal { get; set; } + + [AutoGenerateColumn(Ignore = true)] + [Navigate(nameof(OrderID))] + public virtual List? OrderDetailss { get; set; } + + + public static void DemoDatas(IFreeSql fsql) + { + var Randomer = new Random(); + var res = fsql!.Select().Count(); + if (res == 0) + { + var items = new List(); + for (int i = 1; i < 15; i++) + { + var demo = Enumerable.Range(1, 10).Select((j, index) => + new Orders + { + OrderID = i, + OrderDate = DateTime.Now.Date.AddDays(-(15 - i)), + SubTotal = Randomer.Next(200, 370), + OrderDetailss = Enumerable.Range(5, 20).Select((j, index) => + new OrderDetails + { + OrderID = i, + BarCode = Randomer.Next(100000, 9000000).ToString(), + Quantity = Randomer.Next(10, 30) + }).ToList() + }); + items.AddRange(demo.ToList()); + } + + var repo = fsql.GetRepository();//仓库类 + repo.DbContextOptions.EnableAddOrUpdateNavigateList = true; //开启一对多,多对多级联保存功能 + repo.Insert(items); + } + +} + +} +/// +/// 订单详单 +/// +public partial class OrderDetails +{ + + [JsonProperty, Column(IsIdentity = true)] + public int ID { get; set; } + + [JsonProperty] + public int OrderID { get; set; } + + [JsonProperty, Column(StringLength = -1)] + [DisplayName("条码")] + public string? BarCode { get; set; } + + [AutoGenerateColumn(FormatString = "N0", Align = Alignment.Center)] + [JsonProperty, Column(DbType = "numeric(18,3)")] + [DisplayName("数量")] + public decimal Quantity { get; set; } + +} diff --git a/b06chart/Pages/DayReport.razor b/b06chart/Pages/DayReport.razor new file mode 100644 index 0000000..8a3d1a6 --- /dev/null +++ b/b06chart/Pages/DayReport.razor @@ -0,0 +1,22 @@ +@page "/TopSales" +@namespace b06chart +

日报表

+ + + + + + +
diff --git a/b06chart/Pages/DayReport.razor.cs b/b06chart/Pages/DayReport.razor.cs new file mode 100644 index 0000000..9c50efb --- /dev/null +++ b/b06chart/Pages/DayReport.razor.cs @@ -0,0 +1,59 @@ +using Blazor100.Data; +using BootstrapBlazor.Components; +using Microsoft.AspNetCore.Components; + +namespace b06chart +{ + public partial class DayReport + { + [Inject] IFreeSql? fsql { get; set; } + [Inject] ToastService? toastService { get; set; } + List orders { get; set; } = new List(); + + ChartsBase charts; + decimal Total { get; set; } + string TotalString2 { get; set; } + private Task 数据生成(ChartDataSource ds) + { + var orders = fsql.Select() + .Where(a => a.OrderDate.Month == charts. Month && + a.OrderDate.Year == charts.Year) + .GroupBy(a => new + { + a.OrderDate.Day + }) + .ToList(a => new + { + cou1 = a.Count(), + OrderDate = a.Key.Day, + Total = a.Sum(a.Value.SubTotal) + }); + + orders = orders.OrderBy(a => a.OrderDate).ToList(); + + ds.Labels = orders.Select(a => a.OrderDate.ToString()); + + ds.Data.Add(new ChartDataset() + { + Label = $"单据数", + Data = orders.Select(a => a.cou1).Cast() + }); + ds.Data.Add(new ChartDataset() + { + Label = $"金额", + Data = orders.Select(a => a.Total).Cast() + }); + + return Task.CompletedTask; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + Orders.DemoDatas(fsql); + } + } + + } +} diff --git a/b06chart/Pages/OrdersTopSalesCharts.razor b/b06chart/Pages/OrdersTopSalesCharts.razor new file mode 100644 index 0000000..87feed4 --- /dev/null +++ b/b06chart/Pages/OrdersTopSalesCharts.razor @@ -0,0 +1,20 @@ +@page "/TopSales" +@namespace b06chart +

销售排行榜

+ + + + +
diff --git a/b06chart/Pages/OrdersTopSalesCharts.razor.cs b/b06chart/Pages/OrdersTopSalesCharts.razor.cs new file mode 100644 index 0000000..6cbd351 --- /dev/null +++ b/b06chart/Pages/OrdersTopSalesCharts.razor.cs @@ -0,0 +1,68 @@ +using Blazor100.Data; +using BootstrapBlazor.Components; +using Microsoft.AspNetCore.Components; + +namespace b06chart +{ + public partial class OrdersTopSalesCharts + { + [Inject] IFreeSql? fsql { get; set; } + [Inject] ToastService? toastService { get; set; } + List orders { get; set; } = new List(); + + ChartsBase charts; + decimal Total { get; set; } + string TotalString2 { get; set; } + private Task 数据生成(ChartDataSource ds) + { + //var 起始日期 = (new DateTime(charts.Year, charts.Month,1)).FirstDay(); + + //var 结束日期 = 起始日期.LastDay(); + + //orders = reportService.销售排行榜(起始日期, 结束日期, "", 取记录数:30); + + //结束日期 = 结束日期.Date.AddDays(1).AddSeconds(-1); + //var selector = fsql.Select() + // .Where(a => a.OrdersLites.Status == "已结账") + // .WhereIf(!全部日期, a => a.OrdersLites.OrderDate.Between(起始日期, 结束日期)) + // .WhereIf(!string.IsNullOrEmpty(搜索) && 精确, a => a.BarCode == 搜索 || a.UserCode == 搜索) + // .WhereIf(!string.IsNullOrEmpty(搜索) && !精确, a => a.BarCode.Contains(搜索) || a.UserCode.Contains(搜索) || a.ProductName.Contains(搜索)) + // .Include(a => a.ProductsLites.Suppliers) + // .GroupBy(a => new { a.BarCode, a.UserCode, a.ProductName, a.ProductsLites }) + // .OrderByDescending(a => a.Sum(a.Value.Quantity)); + //if (取记录数 != null) selector = selector.Take(取记录数.Value); + + //var selectDto = selector.ToList(a => new ProductsStock销售排行榜 + //{ + // SupplierName = a.Key.ProductsLites == null ? "" : a.Key.ProductsLites.Suppliers == null ? "" : $"[{a.Key.ProductsLites.Suppliers.SupplierID}]{a.Key.ProductsLites.Suppliers.CompanyName}", + // BarCode = a.Value.BarCode, + // UserCode = a.Value.UserCode, + // ProductName = a.Value.ProductName, + // Quantity = a.Sum(a.Value.Quantity) + //} + // ); + + + //ds.Labels = orders.Select(a => $"{a.ProductName}"); + + //ds.Data.Add(new ChartDataset() + //{ + // Label = $"销售量", + // Data = orders.Select(a => a.Quantity).Cast() + //}); + + //Total = orders.Sum(a => a.Quantity); + + return Task.CompletedTask; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + Orders.DemoDatas(fsql); + } + } + + } +} diff --git a/b06chart/Program.cs b/b06chart/Program.cs index 5b5389e..d6e4613 100644 --- a/b06chart/Program.cs +++ b/b06chart/Program.cs @@ -8,6 +8,18 @@ builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); builder.Services.AddSingleton(); +builder.Services.AddFreeSql(option => +{ + option.UseConnectionString(FreeSql.DataType.Sqlite, "Data Source=test.db;") //Ҳдļ +#if DEBUG + //:Զͬʵ + .UseAutoSyncStructure(true) + .UseNoneCommandParameter(true) + //sql + .UseMonitorCommand(cmd => System.Console.WriteLine(cmd.CommandText)) +#endif + ; +}); builder.Services.AddBootstrapBlazor(); var app = builder.Build(); diff --git a/b06chart/Shared/NavMenu.razor b/b06chart/Shared/NavMenu.razor index 90351df..9cfec49 100644 --- a/b06chart/Shared/NavMenu.razor +++ b/b06chart/Shared/NavMenu.razor @@ -14,16 +14,16 @@ Home - *@ diff --git a/b06chart/_Imports.razor b/b06chart/_Imports.razor index 5f7ab16..5134df4 100644 --- a/b06chart/_Imports.razor +++ b/b06chart/_Imports.razor @@ -9,3 +9,4 @@ @using b06chart @using b06chart.Shared @using BootstrapBlazor.Components +@using Blazor100.Data diff --git a/b06chart/b06chart.csproj b/b06chart/b06chart.csproj index 9f4ea3b..f0ef322 100644 --- a/b06chart/b06chart.csproj +++ b/b06chart/b06chart.csproj @@ -1,15 +1,18 @@ - - net6.0 - enable - enable - + + net6.0 + enable + enable + - - - - - + + + + + + + +