Commit 0d4ee10b78486e1412d83ebc3ab573b09ebe15c9
Merge branch 'main' of http://39.98.150.180/wangming/Food-Labeling-Management-Platform
Showing
45 changed files
with
2629 additions
and
0 deletions
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/Label/LabelCreateInputVo.cs
0 → 100644
| 1 | +namespace FoodLabeling.Application.Contracts.Dtos.Label; | |
| 2 | + | |
| 3 | +public class LabelCreateInputVo | |
| 4 | +{ | |
| 5 | + public string LabelCode { get; set; } = string.Empty; | |
| 6 | + | |
| 7 | + public string LabelName { get; set; } = string.Empty; | |
| 8 | + | |
| 9 | + public string TemplateCode { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public string LocationId { get; set; } = string.Empty; | |
| 12 | + | |
| 13 | + public string LabelCategoryId { get; set; } = string.Empty; | |
| 14 | + | |
| 15 | + public string LabelTypeId { get; set; } = string.Empty; | |
| 16 | + | |
| 17 | + public List<string> ProductIds { get; set; } = new(); | |
| 18 | + | |
| 19 | + public object? LabelInfoJson { get; set; } | |
| 20 | + | |
| 21 | + public bool State { get; set; } = true; | |
| 22 | +} | |
| 23 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/Label/LabelGetListInputVo.cs
0 → 100644
| 1 | +using Volo.Abp.Application.Dtos; | |
| 2 | + | |
| 3 | +namespace FoodLabeling.Application.Contracts.Dtos.Label; | |
| 4 | + | |
| 5 | +/// <summary> | |
| 6 | +/// 标签分页列表入参(按产品展示多个标签) | |
| 7 | +/// </summary> | |
| 8 | +public class LabelGetListInputVo : PagedAndSortedResultRequestDto | |
| 9 | +{ | |
| 10 | + public string? Keyword { get; set; } | |
| 11 | + | |
| 12 | + /// <summary> | |
| 13 | + /// 门店Id(可选) | |
| 14 | + /// </summary> | |
| 15 | + public string? LocationId { get; set; } | |
| 16 | + | |
| 17 | + /// <summary> | |
| 18 | + /// 产品Id(可选;用于“一个产品展示多个标签”) | |
| 19 | + /// </summary> | |
| 20 | + public string? ProductId { get; set; } | |
| 21 | + | |
| 22 | + public string? LabelCategoryId { get; set; } | |
| 23 | + | |
| 24 | + public string? LabelTypeId { get; set; } | |
| 25 | + | |
| 26 | + /// <summary> | |
| 27 | + /// 模板编码(可选) | |
| 28 | + /// </summary> | |
| 29 | + public string? TemplateCode { get; set; } | |
| 30 | + | |
| 31 | + public bool? State { get; set; } | |
| 32 | +} | |
| 33 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/Label/LabelGetListOutputDto.cs
0 → 100644
| 1 | +namespace FoodLabeling.Application.Contracts.Dtos.Label; | |
| 2 | + | |
| 3 | +public class LabelGetListOutputDto | |
| 4 | +{ | |
| 5 | + public string Id { get; set; } = string.Empty; | |
| 6 | + | |
| 7 | + public string LabelName { get; set; } = string.Empty; | |
| 8 | + | |
| 9 | + public string LocationName { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public string LabelCategoryName { get; set; } = string.Empty; | |
| 12 | + | |
| 13 | + public string ProductCategoryName { get; set; } = string.Empty; | |
| 14 | + | |
| 15 | + public string ProductName { get; set; } = string.Empty; | |
| 16 | + | |
| 17 | + public string TemplateName { get; set; } = string.Empty; | |
| 18 | + | |
| 19 | + public string LabelTypeName { get; set; } = string.Empty; | |
| 20 | + | |
| 21 | + public bool State { get; set; } | |
| 22 | + | |
| 23 | + public DateTime LastEdited { get; set; } | |
| 24 | + | |
| 25 | + /// <summary> | |
| 26 | + /// 模板缺失字段告警(当前阶段暂定 false) | |
| 27 | + /// </summary> | |
| 28 | + public bool HasError { get; set; } | |
| 29 | +} | |
| 30 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/Label/LabelGetOutputDto.cs
0 → 100644
| 1 | +namespace FoodLabeling.Application.Contracts.Dtos.Label; | |
| 2 | + | |
| 3 | +public class LabelGetOutputDto | |
| 4 | +{ | |
| 5 | + public string Id { get; set; } = string.Empty; | |
| 6 | + | |
| 7 | + public string LabelName { get; set; } = string.Empty; | |
| 8 | + | |
| 9 | + public string LocationId { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public string LocationName { get; set; } = string.Empty; | |
| 12 | + | |
| 13 | + public string LabelCategoryId { get; set; } = string.Empty; | |
| 14 | + | |
| 15 | + public string LabelCategoryName { get; set; } = string.Empty; | |
| 16 | + | |
| 17 | + public string LabelTypeId { get; set; } = string.Empty; | |
| 18 | + | |
| 19 | + public string LabelTypeName { get; set; } = string.Empty; | |
| 20 | + | |
| 21 | + public string TemplateCode { get; set; } = string.Empty; | |
| 22 | + | |
| 23 | + public string TemplateName { get; set; } = string.Empty; | |
| 24 | + | |
| 25 | + public bool State { get; set; } | |
| 26 | + | |
| 27 | + public object? LabelInfoJson { get; set; } | |
| 28 | + | |
| 29 | + public List<string> ProductIds { get; set; } = new(); | |
| 30 | +} | |
| 31 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/Label/LabelUpdateInputVo.cs
0 → 100644
| 1 | +namespace FoodLabeling.Application.Contracts.Dtos.Label; | |
| 2 | + | |
| 3 | +public class LabelUpdateInputVo | |
| 4 | +{ | |
| 5 | + public string LabelName { get; set; } = string.Empty; | |
| 6 | + | |
| 7 | + public string TemplateCode { get; set; } = string.Empty; | |
| 8 | + | |
| 9 | + public string LocationId { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public string LabelCategoryId { get; set; } = string.Empty; | |
| 12 | + | |
| 13 | + public string LabelTypeId { get; set; } = string.Empty; | |
| 14 | + | |
| 15 | + public List<string> ProductIds { get; set; } = new(); | |
| 16 | + | |
| 17 | + public object? LabelInfoJson { get; set; } | |
| 18 | + | |
| 19 | + public bool State { get; set; } = true; | |
| 20 | +} | |
| 21 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelCategory/LabelCategoryCreateInputVo.cs
0 → 100644
| 1 | +namespace FoodLabeling.Application.Contracts.Dtos.LabelCategory; | |
| 2 | + | |
| 3 | +public class LabelCategoryCreateInputVo | |
| 4 | +{ | |
| 5 | + public string CategoryCode { get; set; } = string.Empty; | |
| 6 | + | |
| 7 | + public string CategoryName { get; set; } = string.Empty; | |
| 8 | + | |
| 9 | + public string? CategoryPhotoUrl { get; set; } | |
| 10 | + | |
| 11 | + public bool State { get; set; } = true; | |
| 12 | + | |
| 13 | + public int OrderNum { get; set; } | |
| 14 | +} | |
| 15 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelCategory/LabelCategoryGetListInputVo.cs
0 → 100644
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelCategory/LabelCategoryGetListOutputDto.cs
0 → 100644
| 1 | +namespace FoodLabeling.Application.Contracts.Dtos.LabelCategory; | |
| 2 | + | |
| 3 | +public class LabelCategoryGetListOutputDto | |
| 4 | +{ | |
| 5 | + public string Id { get; set; } = string.Empty; | |
| 6 | + | |
| 7 | + public string CategoryCode { get; set; } = string.Empty; | |
| 8 | + | |
| 9 | + public string CategoryName { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public string? CategoryPhotoUrl { get; set; } | |
| 12 | + | |
| 13 | + public bool State { get; set; } | |
| 14 | + | |
| 15 | + public int OrderNum { get; set; } | |
| 16 | + | |
| 17 | + public long NoOfLabels { get; set; } | |
| 18 | + | |
| 19 | + public DateTime LastEdited { get; set; } | |
| 20 | +} | |
| 21 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelCategory/LabelCategoryGetOutputDto.cs
0 → 100644
| 1 | +namespace FoodLabeling.Application.Contracts.Dtos.LabelCategory; | |
| 2 | + | |
| 3 | +public class LabelCategoryGetOutputDto | |
| 4 | +{ | |
| 5 | + public string Id { get; set; } = string.Empty; | |
| 6 | + | |
| 7 | + public string CategoryCode { get; set; } = string.Empty; | |
| 8 | + | |
| 9 | + public string CategoryName { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public string? CategoryPhotoUrl { get; set; } | |
| 12 | + | |
| 13 | + public bool State { get; set; } | |
| 14 | + | |
| 15 | + public int OrderNum { get; set; } | |
| 16 | +} | |
| 17 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelCategory/LabelCategoryUpdateInputVo.cs
0 → 100644
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelMultipleOption/LabelMultipleOptionCreateInputVo.cs
0 → 100644
| 1 | +namespace FoodLabeling.Application.Contracts.Dtos.LabelMultipleOption; | |
| 2 | + | |
| 3 | +public class LabelMultipleOptionCreateInputVo | |
| 4 | +{ | |
| 5 | + public string OptionCode { get; set; } = string.Empty; | |
| 6 | + | |
| 7 | + public string OptionName { get; set; } = string.Empty; | |
| 8 | + | |
| 9 | + public string? OptionValuesJson { get; set; } | |
| 10 | + | |
| 11 | + public bool State { get; set; } = true; | |
| 12 | + | |
| 13 | + public int OrderNum { get; set; } | |
| 14 | +} | |
| 15 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelMultipleOption/LabelMultipleOptionGetListInputVo.cs
0 → 100644
| 1 | +using Volo.Abp.Application.Dtos; | |
| 2 | + | |
| 3 | +namespace FoodLabeling.Application.Contracts.Dtos.LabelMultipleOption; | |
| 4 | + | |
| 5 | +public class LabelMultipleOptionGetListInputVo : PagedAndSortedResultRequestDto | |
| 6 | +{ | |
| 7 | + public string? Keyword { get; set; } | |
| 8 | + | |
| 9 | + public bool? State { get; set; } | |
| 10 | +} | |
| 11 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelMultipleOption/LabelMultipleOptionGetListOutputDto.cs
0 → 100644
| 1 | +namespace FoodLabeling.Application.Contracts.Dtos.LabelMultipleOption; | |
| 2 | + | |
| 3 | +public class LabelMultipleOptionGetListOutputDto | |
| 4 | +{ | |
| 5 | + public string Id { get; set; } = string.Empty; | |
| 6 | + | |
| 7 | + public string OptionCode { get; set; } = string.Empty; | |
| 8 | + | |
| 9 | + public string OptionName { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public string? OptionValuesJson { get; set; } | |
| 12 | + | |
| 13 | + public bool State { get; set; } | |
| 14 | + | |
| 15 | + public int OrderNum { get; set; } | |
| 16 | + | |
| 17 | + public DateTime LastEdited { get; set; } | |
| 18 | +} | |
| 19 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelMultipleOption/LabelMultipleOptionGetOutputDto.cs
0 → 100644
| 1 | +namespace FoodLabeling.Application.Contracts.Dtos.LabelMultipleOption; | |
| 2 | + | |
| 3 | +public class LabelMultipleOptionGetOutputDto | |
| 4 | +{ | |
| 5 | + public string Id { get; set; } = string.Empty; | |
| 6 | + | |
| 7 | + public string OptionCode { get; set; } = string.Empty; | |
| 8 | + | |
| 9 | + public string OptionName { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public string? OptionValuesJson { get; set; } | |
| 12 | + | |
| 13 | + public bool State { get; set; } | |
| 14 | + | |
| 15 | + public int OrderNum { get; set; } | |
| 16 | +} | |
| 17 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelMultipleOption/LabelMultipleOptionUpdateInputVo.cs
0 → 100644
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelTemplate/LabelTemplateCreateInputVo.cs
0 → 100644
| 1 | +using System.Text.Json.Serialization; | |
| 2 | + | |
| 3 | +namespace FoodLabeling.Application.Contracts.Dtos.LabelTemplate; | |
| 4 | + | |
| 5 | +public class LabelTemplateCreateInputVo | |
| 6 | +{ | |
| 7 | + /// <summary> | |
| 8 | + /// editor JSON 里的 id,对应数据库 fl_label_template.TemplateCode | |
| 9 | + /// </summary> | |
| 10 | + [JsonPropertyName("id")] | |
| 11 | + public string TemplateCode { get; set; } = string.Empty; | |
| 12 | + | |
| 13 | + /// <summary> | |
| 14 | + /// editor JSON 里的 name,对应数据库 fl_label_template.TemplateName | |
| 15 | + /// </summary> | |
| 16 | + [JsonPropertyName("name")] | |
| 17 | + public string TemplateName { get; set; } = string.Empty; | |
| 18 | + | |
| 19 | + [JsonPropertyName("labelType")] | |
| 20 | + public string? LabelType { get; set; } | |
| 21 | + | |
| 22 | + [JsonPropertyName("unit")] | |
| 23 | + public string Unit { get; set; } = "inch"; | |
| 24 | + | |
| 25 | + [JsonPropertyName("width")] | |
| 26 | + public decimal Width { get; set; } | |
| 27 | + | |
| 28 | + [JsonPropertyName("height")] | |
| 29 | + public decimal Height { get; set; } | |
| 30 | + | |
| 31 | + /// <summary> | |
| 32 | + /// editor JSON 里的 appliedLocation(ALL / SPECIFIED) | |
| 33 | + /// </summary> | |
| 34 | + [JsonPropertyName("appliedLocation")] | |
| 35 | + public string AppliedLocationType { get; set; } = "ALL"; | |
| 36 | + | |
| 37 | + [JsonPropertyName("showRuler")] | |
| 38 | + public bool ShowRuler { get; set; } = true; | |
| 39 | + | |
| 40 | + [JsonPropertyName("showGrid")] | |
| 41 | + public bool ShowGrid { get; set; } = true; | |
| 42 | + | |
| 43 | + /// <summary> | |
| 44 | + /// 预留:前端可能不传;如果不传则默认 true | |
| 45 | + /// </summary> | |
| 46 | + [JsonPropertyName("state")] | |
| 47 | + public bool State { get; set; } = true; | |
| 48 | + | |
| 49 | + /// <summary> | |
| 50 | + /// elements(前端 editor 的 elements[],会全量重建) | |
| 51 | + /// </summary> | |
| 52 | + [JsonPropertyName("elements")] | |
| 53 | + public List<LabelTemplateElementDto> Elements { get; set; } = new(); | |
| 54 | + | |
| 55 | + /// <summary> | |
| 56 | + /// 当 AppliedLocationType=SPECIFIED 时生效 | |
| 57 | + /// </summary> | |
| 58 | + [JsonPropertyName("appliedLocationIds")] | |
| 59 | + public List<string> AppliedLocationIds { get; set; } = new(); | |
| 60 | +} | |
| 61 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelTemplate/LabelTemplateElementDto.cs
0 → 100644
| 1 | +using System.Text.Json.Serialization; | |
| 2 | + | |
| 3 | +namespace FoodLabeling.Application.Contracts.Dtos.LabelTemplate; | |
| 4 | + | |
| 5 | +/// <summary> | |
| 6 | +/// 模板元素(对齐你给的 editor JSON:id/type/x/y/width/height/rotation/border/config) | |
| 7 | +/// </summary> | |
| 8 | +public class LabelTemplateElementDto | |
| 9 | +{ | |
| 10 | + [JsonPropertyName("id")] | |
| 11 | + public string Id { get; set; } = string.Empty; | |
| 12 | + | |
| 13 | + [JsonPropertyName("type")] | |
| 14 | + public string ElementType { get; set; } = string.Empty; | |
| 15 | + | |
| 16 | + [JsonPropertyName("x")] | |
| 17 | + public decimal PosX { get; set; } | |
| 18 | + | |
| 19 | + [JsonPropertyName("y")] | |
| 20 | + public decimal PosY { get; set; } | |
| 21 | + | |
| 22 | + [JsonPropertyName("width")] | |
| 23 | + public decimal Width { get; set; } | |
| 24 | + | |
| 25 | + [JsonPropertyName("height")] | |
| 26 | + public decimal Height { get; set; } | |
| 27 | + | |
| 28 | + [JsonPropertyName("rotation")] | |
| 29 | + public string Rotation { get; set; } = "horizontal"; | |
| 30 | + | |
| 31 | + [JsonPropertyName("border")] | |
| 32 | + public string BorderType { get; set; } = "none"; | |
| 33 | + | |
| 34 | + [JsonPropertyName("zIndex")] | |
| 35 | + public int ZIndex { get; set; } | |
| 36 | + | |
| 37 | + [JsonPropertyName("orderNum")] | |
| 38 | + public int OrderNum { get; set; } | |
| 39 | + | |
| 40 | + /// <summary> | |
| 41 | + /// 值来源:FIXED / AUTO_DB / PRINT_INPUT | |
| 42 | + /// </summary> | |
| 43 | + [JsonPropertyName("valueSourceType")] | |
| 44 | + public string ValueSourceType { get; set; } = "FIXED"; | |
| 45 | + | |
| 46 | + [JsonPropertyName("bindingExpr")] | |
| 47 | + public string? BindingExpr { get; set; } | |
| 48 | + | |
| 49 | + [JsonPropertyName("autoQueryKey")] | |
| 50 | + public string? AutoQueryKey { get; set; } | |
| 51 | + | |
| 52 | + [JsonPropertyName("inputKey")] | |
| 53 | + public string? InputKey { get; set; } | |
| 54 | + | |
| 55 | + [JsonPropertyName("isRequiredInput")] | |
| 56 | + public bool IsRequiredInput { get; set; } | |
| 57 | + | |
| 58 | + /// <summary> | |
| 59 | + /// 元素配置 | |
| 60 | + /// </summary> | |
| 61 | + [JsonPropertyName("config")] | |
| 62 | + public object? ConfigJson { get; set; } | |
| 63 | +} | |
| 64 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelTemplate/LabelTemplateGetListInputVo.cs
0 → 100644
| 1 | +using Volo.Abp.Application.Dtos; | |
| 2 | + | |
| 3 | +namespace FoodLabeling.Application.Contracts.Dtos.LabelTemplate; | |
| 4 | + | |
| 5 | +/// <summary> | |
| 6 | +/// 标签模板分页查询入参 | |
| 7 | +/// </summary> | |
| 8 | +public class LabelTemplateGetListInputVo : PagedAndSortedResultRequestDto | |
| 9 | +{ | |
| 10 | + /// <summary> | |
| 11 | + /// 关键字(模板名称/模板编码) | |
| 12 | + /// </summary> | |
| 13 | + public string? Keyword { get; set; } | |
| 14 | + | |
| 15 | + /// <summary> | |
| 16 | + /// 门店Id(用于筛选:ALL 或指定门店) | |
| 17 | + /// </summary> | |
| 18 | + public string? LocationId { get; set; } | |
| 19 | + | |
| 20 | + /// <summary> | |
| 21 | + /// 标签类型(例如 PRICE) | |
| 22 | + /// </summary> | |
| 23 | + public string? LabelType { get; set; } | |
| 24 | + | |
| 25 | + /// <summary> | |
| 26 | + /// 状态 | |
| 27 | + /// </summary> | |
| 28 | + public bool? State { get; set; } | |
| 29 | +} | |
| 30 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelTemplate/LabelTemplateGetListOutputDto.cs
0 → 100644
| 1 | +namespace FoodLabeling.Application.Contracts.Dtos.LabelTemplate; | |
| 2 | + | |
| 3 | +public class LabelTemplateGetListOutputDto | |
| 4 | +{ | |
| 5 | + public string Id { get; set; } = string.Empty; | |
| 6 | + | |
| 7 | + public string TemplateCode { get; set; } = string.Empty; | |
| 8 | + | |
| 9 | + public string TemplateName { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public string? LabelType { get; set; } | |
| 12 | + | |
| 13 | + /// <summary> | |
| 14 | + /// 位置展示:All Locations 或首个指定门店的名称 | |
| 15 | + /// </summary> | |
| 16 | + public string LocationText { get; set; } = string.Empty; | |
| 17 | + | |
| 18 | + /// <summary> | |
| 19 | + /// elements 数量(Contents) | |
| 20 | + /// </summary> | |
| 21 | + public int ContentsCount { get; set; } | |
| 22 | + | |
| 23 | + public string SizeText { get; set; } = string.Empty; | |
| 24 | + | |
| 25 | + public int VersionNo { get; set; } | |
| 26 | + | |
| 27 | + public DateTime LastEdited { get; set; } | |
| 28 | +} | |
| 29 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelTemplate/LabelTemplateGetOutputDto.cs
0 → 100644
| 1 | +namespace FoodLabeling.Application.Contracts.Dtos.LabelTemplate; | |
| 2 | + | |
| 3 | +public class LabelTemplateGetOutputDto | |
| 4 | +{ | |
| 5 | + public string Id { get; set; } = string.Empty; | |
| 6 | + | |
| 7 | + public string TemplateCode { get; set; } = string.Empty; | |
| 8 | + | |
| 9 | + public string TemplateName { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public string? LabelType { get; set; } | |
| 12 | + | |
| 13 | + public string Unit { get; set; } = string.Empty; | |
| 14 | + | |
| 15 | + public decimal Width { get; set; } | |
| 16 | + | |
| 17 | + public decimal Height { get; set; } | |
| 18 | + | |
| 19 | + public string AppliedLocationType { get; set; } = "ALL"; | |
| 20 | + | |
| 21 | + public bool ShowRuler { get; set; } | |
| 22 | + | |
| 23 | + public bool ShowGrid { get; set; } | |
| 24 | + | |
| 25 | + public int VersionNo { get; set; } | |
| 26 | + | |
| 27 | + public bool State { get; set; } | |
| 28 | + | |
| 29 | + public List<LabelTemplateElementDto> Elements { get; set; } = new(); | |
| 30 | + | |
| 31 | + public List<string> AppliedLocationIds { get; set; } = new(); | |
| 32 | +} | |
| 33 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelTemplate/LabelTemplateUpdateInputVo.cs
0 → 100644
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelType/LabelTypeCreateInputVo.cs
0 → 100644
| 1 | +namespace FoodLabeling.Application.Contracts.Dtos.LabelType; | |
| 2 | + | |
| 3 | +public class LabelTypeCreateInputVo | |
| 4 | +{ | |
| 5 | + public string TypeCode { get; set; } = string.Empty; | |
| 6 | + | |
| 7 | + public string TypeName { get; set; } = string.Empty; | |
| 8 | + | |
| 9 | + public bool State { get; set; } = true; | |
| 10 | + | |
| 11 | + public int OrderNum { get; set; } | |
| 12 | +} | |
| 13 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelType/LabelTypeGetListInputVo.cs
0 → 100644
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelType/LabelTypeGetListOutputDto.cs
0 → 100644
| 1 | +namespace FoodLabeling.Application.Contracts.Dtos.LabelType; | |
| 2 | + | |
| 3 | +public class LabelTypeGetListOutputDto | |
| 4 | +{ | |
| 5 | + public string Id { get; set; } = string.Empty; | |
| 6 | + | |
| 7 | + public string TypeCode { get; set; } = string.Empty; | |
| 8 | + | |
| 9 | + public string TypeName { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public bool State { get; set; } | |
| 12 | + | |
| 13 | + public int OrderNum { get; set; } | |
| 14 | + | |
| 15 | + public long NoOfLabels { get; set; } | |
| 16 | + | |
| 17 | + public DateTime LastEdited { get; set; } | |
| 18 | +} | |
| 19 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelType/LabelTypeGetOutputDto.cs
0 → 100644
| 1 | +namespace FoodLabeling.Application.Contracts.Dtos.LabelType; | |
| 2 | + | |
| 3 | +public class LabelTypeGetOutputDto | |
| 4 | +{ | |
| 5 | + public string Id { get; set; } = string.Empty; | |
| 6 | + | |
| 7 | + public string TypeCode { get; set; } = string.Empty; | |
| 8 | + | |
| 9 | + public string TypeName { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public bool State { get; set; } | |
| 12 | + | |
| 13 | + public int OrderNum { get; set; } | |
| 14 | +} | |
| 15 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/Dtos/LabelType/LabelTypeUpdateInputVo.cs
0 → 100644
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/IServices/ILabelAppService.cs
0 → 100644
| 1 | +using FoodLabeling.Application.Contracts.Dtos.Common; | |
| 2 | +using FoodLabeling.Application.Contracts.Dtos.Label; | |
| 3 | +using Volo.Abp.Application.Dtos; | |
| 4 | +using Volo.Abp.Application.Services; | |
| 5 | + | |
| 6 | +namespace FoodLabeling.Application.Contracts.IServices; | |
| 7 | + | |
| 8 | +/// <summary> | |
| 9 | +/// 标签管理接口(美国版) | |
| 10 | +/// </summary> | |
| 11 | +public interface ILabelAppService : IApplicationService | |
| 12 | +{ | |
| 13 | + /// <summary> | |
| 14 | + /// 按产品分页列表(一个产品展示多个标签) | |
| 15 | + /// </summary> | |
| 16 | + Task<PagedResultWithPageDto<LabelGetListOutputDto>> GetListAsync(LabelGetListInputVo input); | |
| 17 | + | |
| 18 | + /// <summary> | |
| 19 | + /// 标签详情(id=LabelCode) | |
| 20 | + /// </summary> | |
| 21 | + Task<LabelGetOutputDto> GetAsync(string id); | |
| 22 | + | |
| 23 | + /// <summary> | |
| 24 | + /// 新增标签 | |
| 25 | + /// </summary> | |
| 26 | + Task<LabelGetOutputDto> CreateAsync(LabelCreateInputVo input); | |
| 27 | + | |
| 28 | + /// <summary> | |
| 29 | + /// 编辑标签(id=LabelCode) | |
| 30 | + /// </summary> | |
| 31 | + Task<LabelGetOutputDto> UpdateAsync(string id, LabelUpdateInputVo input); | |
| 32 | + | |
| 33 | + /// <summary> | |
| 34 | + /// 删除标签(逻辑删除) | |
| 35 | + /// </summary> | |
| 36 | + Task DeleteAsync(string id); | |
| 37 | + | |
| 38 | + /// <summary> | |
| 39 | + /// 标签预览:解析模板 AUTO_DB/PRINT_INPUT(不做打印落库) | |
| 40 | + /// </summary> | |
| 41 | + Task<LabelTemplatePreviewDto> PreviewAsync(LabelPreviewResolveInputVo input); | |
| 42 | +} | |
| 43 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/IServices/ILabelCategoryAppService.cs
0 → 100644
| 1 | +using FoodLabeling.Application.Contracts.Dtos.Common; | |
| 2 | +using FoodLabeling.Application.Contracts.Dtos.LabelCategory; | |
| 3 | + | |
| 4 | +namespace FoodLabeling.Application.Contracts.IServices; | |
| 5 | + | |
| 6 | +public interface ILabelCategoryAppService | |
| 7 | +{ | |
| 8 | + Task<PagedResultWithPageDto<LabelCategoryGetListOutputDto>> GetListAsync(LabelCategoryGetListInputVo input); | |
| 9 | + | |
| 10 | + Task<LabelCategoryGetOutputDto> GetAsync(string id); | |
| 11 | + | |
| 12 | + Task<LabelCategoryGetOutputDto> CreateAsync(LabelCategoryCreateInputVo input); | |
| 13 | + | |
| 14 | + Task<LabelCategoryGetOutputDto> UpdateAsync(string id, LabelCategoryUpdateInputVo input); | |
| 15 | + | |
| 16 | + Task DeleteAsync(string id); | |
| 17 | +} | |
| 18 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/IServices/ILabelMultipleOptionAppService.cs
0 → 100644
| 1 | +using FoodLabeling.Application.Contracts.Dtos.Common; | |
| 2 | +using FoodLabeling.Application.Contracts.Dtos.LabelMultipleOption; | |
| 3 | + | |
| 4 | +namespace FoodLabeling.Application.Contracts.IServices; | |
| 5 | + | |
| 6 | +public interface ILabelMultipleOptionAppService | |
| 7 | +{ | |
| 8 | + Task<PagedResultWithPageDto<LabelMultipleOptionGetListOutputDto>> GetListAsync(LabelMultipleOptionGetListInputVo input); | |
| 9 | + | |
| 10 | + Task<LabelMultipleOptionGetOutputDto> GetAsync(string id); | |
| 11 | + | |
| 12 | + Task<LabelMultipleOptionGetOutputDto> CreateAsync(LabelMultipleOptionCreateInputVo input); | |
| 13 | + | |
| 14 | + Task<LabelMultipleOptionGetOutputDto> UpdateAsync(string id, LabelMultipleOptionUpdateInputVo input); | |
| 15 | + | |
| 16 | + Task DeleteAsync(string id); | |
| 17 | +} | |
| 18 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/IServices/ILabelTemplateAppService.cs
0 → 100644
| 1 | +using FoodLabeling.Application.Contracts.Dtos.Common; | |
| 2 | +using FoodLabeling.Application.Contracts.Dtos.LabelTemplate; | |
| 3 | +using Volo.Abp.Application.Dtos; | |
| 4 | +using Volo.Abp.Application.Services; | |
| 5 | + | |
| 6 | +namespace FoodLabeling.Application.Contracts.IServices; | |
| 7 | + | |
| 8 | +/// <summary> | |
| 9 | +/// 标签模板管理接口(美国版对外) | |
| 10 | +/// </summary> | |
| 11 | +public interface ILabelTemplateAppService : IApplicationService | |
| 12 | +{ | |
| 13 | + /// <summary> | |
| 14 | + /// 标签模板分页列表 | |
| 15 | + /// </summary> | |
| 16 | + Task<PagedResultWithPageDto<LabelTemplateGetListOutputDto>> GetListAsync(LabelTemplateGetListInputVo input); | |
| 17 | + | |
| 18 | + /// <summary> | |
| 19 | + /// 标签模板详情(含 elements 与适用门店) | |
| 20 | + /// </summary> | |
| 21 | + Task<LabelTemplateGetOutputDto> GetAsync(string id); | |
| 22 | + | |
| 23 | + /// <summary> | |
| 24 | + /// 新增标签模板 | |
| 25 | + /// </summary> | |
| 26 | + Task<LabelTemplateGetOutputDto> CreateAsync(LabelTemplateCreateInputVo input); | |
| 27 | + | |
| 28 | + /// <summary> | |
| 29 | + /// 编辑标签模板(版本号 +1,重建 elements) | |
| 30 | + /// </summary> | |
| 31 | + Task<LabelTemplateGetOutputDto> UpdateAsync(string id, LabelTemplateUpdateInputVo input); | |
| 32 | + | |
| 33 | + /// <summary> | |
| 34 | + /// 删除标签模板(逻辑删除;若已被标签引用则禁止) | |
| 35 | + /// </summary> | |
| 36 | + Task DeleteAsync(string id); | |
| 37 | +} | |
| 38 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application.Contracts/IServices/ILabelTypeAppService.cs
0 → 100644
| 1 | +using FoodLabeling.Application.Contracts.Dtos.Common; | |
| 2 | +using FoodLabeling.Application.Contracts.Dtos.LabelType; | |
| 3 | + | |
| 4 | +namespace FoodLabeling.Application.Contracts.IServices; | |
| 5 | + | |
| 6 | +public interface ILabelTypeAppService | |
| 7 | +{ | |
| 8 | + Task<PagedResultWithPageDto<LabelTypeGetListOutputDto>> GetListAsync(LabelTypeGetListInputVo input); | |
| 9 | + | |
| 10 | + Task<LabelTypeGetOutputDto> GetAsync(string id); | |
| 11 | + | |
| 12 | + Task<LabelTypeGetOutputDto> CreateAsync(LabelTypeCreateInputVo input); | |
| 13 | + | |
| 14 | + Task<LabelTypeGetOutputDto> UpdateAsync(string id, LabelTypeUpdateInputVo input); | |
| 15 | + | |
| 16 | + Task DeleteAsync(string id); | |
| 17 | +} | |
| 18 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/DbModels/FlLabelCategoryDbEntity.cs
0 → 100644
| 1 | +using SqlSugar; | |
| 2 | + | |
| 3 | +namespace FoodLabeling.Application.Services.DbModels; | |
| 4 | + | |
| 5 | +[SugarTable("fl_label_category")] | |
| 6 | +public class FlLabelCategoryDbEntity | |
| 7 | +{ | |
| 8 | + [SugarColumn(IsPrimaryKey = true)] | |
| 9 | + public string Id { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public bool IsDeleted { get; set; } | |
| 12 | + | |
| 13 | + public DateTime CreationTime { get; set; } | |
| 14 | + | |
| 15 | + public string? CreatorId { get; set; } | |
| 16 | + | |
| 17 | + public string? LastModifierId { get; set; } | |
| 18 | + | |
| 19 | + public DateTime? LastModificationTime { get; set; } | |
| 20 | + | |
| 21 | + public string ConcurrencyStamp { get; set; } = string.Empty; | |
| 22 | + | |
| 23 | + public string CategoryCode { get; set; } = string.Empty; | |
| 24 | + | |
| 25 | + public string CategoryName { get; set; } = string.Empty; | |
| 26 | + | |
| 27 | + public string? CategoryPhotoUrl { get; set; } | |
| 28 | + | |
| 29 | + public int OrderNum { get; set; } | |
| 30 | + | |
| 31 | + public bool State { get; set; } | |
| 32 | +} | |
| 33 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/DbModels/FlLabelDbEntity.cs
0 → 100644
| 1 | +using SqlSugar; | |
| 2 | + | |
| 3 | +namespace FoodLabeling.Application.Services.DbModels; | |
| 4 | + | |
| 5 | +[SugarTable("fl_label")] | |
| 6 | +public class FlLabelDbEntity | |
| 7 | +{ | |
| 8 | + [SugarColumn(IsPrimaryKey = true)] | |
| 9 | + public string Id { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public bool IsDeleted { get; set; } | |
| 12 | + | |
| 13 | + public DateTime CreationTime { get; set; } | |
| 14 | + | |
| 15 | + public string? CreatorId { get; set; } | |
| 16 | + | |
| 17 | + public string? LastModifierId { get; set; } | |
| 18 | + | |
| 19 | + public DateTime? LastModificationTime { get; set; } | |
| 20 | + | |
| 21 | + public string ConcurrencyStamp { get; set; } = string.Empty; | |
| 22 | + | |
| 23 | + public string LabelCode { get; set; } = string.Empty; | |
| 24 | + | |
| 25 | + public string LabelName { get; set; } = string.Empty; | |
| 26 | + | |
| 27 | + public string TemplateId { get; set; } = string.Empty; | |
| 28 | + | |
| 29 | + public string? LocationId { get; set; } | |
| 30 | + | |
| 31 | + public string? LabelCategoryId { get; set; } | |
| 32 | + | |
| 33 | + public string? LabelTypeId { get; set; } | |
| 34 | + | |
| 35 | + public string? LabelType { get; set; } | |
| 36 | + | |
| 37 | + public bool State { get; set; } | |
| 38 | + | |
| 39 | + /// <summary> | |
| 40 | + /// json 字段,直接保存为字符串(入参/出参自行序列化/反序列化) | |
| 41 | + /// </summary> | |
| 42 | + public string? LabelInfoJson { get; set; } | |
| 43 | +} | |
| 44 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/DbModels/FlLabelMultipleOptionDbEntity.cs
0 → 100644
| 1 | +using SqlSugar; | |
| 2 | + | |
| 3 | +namespace FoodLabeling.Application.Services.DbModels; | |
| 4 | + | |
| 5 | +[SugarTable("fl_label_multiple_option")] | |
| 6 | +public class FlLabelMultipleOptionDbEntity | |
| 7 | +{ | |
| 8 | + [SugarColumn(IsPrimaryKey = true)] | |
| 9 | + public string Id { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public bool IsDeleted { get; set; } | |
| 12 | + | |
| 13 | + public DateTime CreationTime { get; set; } | |
| 14 | + | |
| 15 | + public string? CreatorId { get; set; } | |
| 16 | + | |
| 17 | + public string? LastModifierId { get; set; } | |
| 18 | + | |
| 19 | + public DateTime? LastModificationTime { get; set; } | |
| 20 | + | |
| 21 | + public string ConcurrencyStamp { get; set; } = string.Empty; | |
| 22 | + | |
| 23 | + public string OptionCode { get; set; } = string.Empty; | |
| 24 | + | |
| 25 | + public string OptionName { get; set; } = string.Empty; | |
| 26 | + | |
| 27 | + public string? OptionValuesJson { get; set; } | |
| 28 | + | |
| 29 | + public int OrderNum { get; set; } | |
| 30 | + | |
| 31 | + public bool State { get; set; } | |
| 32 | +} | |
| 33 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/DbModels/FlLabelProductDbEntity.cs
0 → 100644
| 1 | +using SqlSugar; | |
| 2 | + | |
| 3 | +namespace FoodLabeling.Application.Services.DbModels; | |
| 4 | + | |
| 5 | +[SugarTable("fl_label_product")] | |
| 6 | +public class FlLabelProductDbEntity | |
| 7 | +{ | |
| 8 | + [SugarColumn(IsPrimaryKey = true)] | |
| 9 | + public string Id { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public string LabelId { get; set; } = string.Empty; | |
| 12 | + | |
| 13 | + public string ProductId { get; set; } = string.Empty; | |
| 14 | +} | |
| 15 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/DbModels/FlLabelTemplateDbEntity.cs
0 → 100644
| 1 | +using SqlSugar; | |
| 2 | + | |
| 3 | +namespace FoodLabeling.Application.Services.DbModels; | |
| 4 | + | |
| 5 | +[SugarTable("fl_label_template")] | |
| 6 | +public class FlLabelTemplateDbEntity | |
| 7 | +{ | |
| 8 | + [SugarColumn(IsPrimaryKey = true)] | |
| 9 | + public string Id { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public bool IsDeleted { get; set; } | |
| 12 | + | |
| 13 | + public DateTime CreationTime { get; set; } | |
| 14 | + | |
| 15 | + public string? CreatorId { get; set; } | |
| 16 | + | |
| 17 | + public string? LastModifierId { get; set; } | |
| 18 | + | |
| 19 | + public DateTime? LastModificationTime { get; set; } | |
| 20 | + | |
| 21 | + public string ConcurrencyStamp { get; set; } = string.Empty; | |
| 22 | + | |
| 23 | + public string TemplateCode { get; set; } = string.Empty; | |
| 24 | + | |
| 25 | + public string TemplateName { get; set; } = string.Empty; | |
| 26 | + | |
| 27 | + public string? LabelType { get; set; } | |
| 28 | + | |
| 29 | + public string Unit { get; set; } = "inch"; | |
| 30 | + | |
| 31 | + public decimal Width { get; set; } | |
| 32 | + | |
| 33 | + public decimal Height { get; set; } | |
| 34 | + | |
| 35 | + public string AppliedLocationType { get; set; } = "ALL"; | |
| 36 | + | |
| 37 | + public bool ShowRuler { get; set; } | |
| 38 | + | |
| 39 | + public bool ShowGrid { get; set; } | |
| 40 | + | |
| 41 | + public int VersionNo { get; set; } | |
| 42 | + | |
| 43 | + public bool State { get; set; } | |
| 44 | +} | |
| 45 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/DbModels/FlLabelTemplateElementDbEntity.cs
0 → 100644
| 1 | +using SqlSugar; | |
| 2 | + | |
| 3 | +namespace FoodLabeling.Application.Services.DbModels; | |
| 4 | + | |
| 5 | +[SugarTable("fl_label_template_element")] | |
| 6 | +public class FlLabelTemplateElementDbEntity | |
| 7 | +{ | |
| 8 | + [SugarColumn(IsPrimaryKey = true)] | |
| 9 | + public string Id { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public string TemplateId { get; set; } = string.Empty; | |
| 12 | + | |
| 13 | + public string ElementKey { get; set; } = string.Empty; | |
| 14 | + | |
| 15 | + public string ElementType { get; set; } = string.Empty; | |
| 16 | + | |
| 17 | + public decimal PosX { get; set; } | |
| 18 | + | |
| 19 | + public decimal PosY { get; set; } | |
| 20 | + | |
| 21 | + public decimal Width { get; set; } | |
| 22 | + | |
| 23 | + public decimal Height { get; set; } | |
| 24 | + | |
| 25 | + public string Rotation { get; set; } = "horizontal"; | |
| 26 | + | |
| 27 | + public string BorderType { get; set; } = "none"; | |
| 28 | + | |
| 29 | + public int ZIndex { get; set; } | |
| 30 | + | |
| 31 | + public int OrderNum { get; set; } | |
| 32 | + | |
| 33 | + public string ValueSourceType { get; set; } = "FIXED"; | |
| 34 | + | |
| 35 | + public string? BindingExpr { get; set; } | |
| 36 | + | |
| 37 | + public string? AutoQueryKey { get; set; } | |
| 38 | + | |
| 39 | + public string? InputKey { get; set; } | |
| 40 | + | |
| 41 | + public bool IsRequiredInput { get; set; } | |
| 42 | + | |
| 43 | + public string? ConfigJson { get; set; } | |
| 44 | +} | |
| 45 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/DbModels/FlLabelTemplateLocationDbEntity.cs
0 → 100644
| 1 | +using SqlSugar; | |
| 2 | + | |
| 3 | +namespace FoodLabeling.Application.Services.DbModels; | |
| 4 | + | |
| 5 | +[SugarTable("fl_label_template_location")] | |
| 6 | +public class FlLabelTemplateLocationDbEntity | |
| 7 | +{ | |
| 8 | + [SugarColumn(IsPrimaryKey = true)] | |
| 9 | + public string Id { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public string TemplateId { get; set; } = string.Empty; | |
| 12 | + | |
| 13 | + public string LocationId { get; set; } = string.Empty; | |
| 14 | +} | |
| 15 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/DbModels/FlLabelTypeDbEntity.cs
0 → 100644
| 1 | +using SqlSugar; | |
| 2 | + | |
| 3 | +namespace FoodLabeling.Application.Services.DbModels; | |
| 4 | + | |
| 5 | +[SugarTable("fl_label_type")] | |
| 6 | +public class FlLabelTypeDbEntity | |
| 7 | +{ | |
| 8 | + [SugarColumn(IsPrimaryKey = true)] | |
| 9 | + public string Id { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public bool IsDeleted { get; set; } | |
| 12 | + | |
| 13 | + public DateTime CreationTime { get; set; } | |
| 14 | + | |
| 15 | + public string? CreatorId { get; set; } | |
| 16 | + | |
| 17 | + public string? LastModifierId { get; set; } | |
| 18 | + | |
| 19 | + public DateTime? LastModificationTime { get; set; } | |
| 20 | + | |
| 21 | + public string ConcurrencyStamp { get; set; } = string.Empty; | |
| 22 | + | |
| 23 | + public string TypeCode { get; set; } = string.Empty; | |
| 24 | + | |
| 25 | + public string TypeName { get; set; } = string.Empty; | |
| 26 | + | |
| 27 | + public int OrderNum { get; set; } | |
| 28 | + | |
| 29 | + public bool State { get; set; } | |
| 30 | +} | |
| 31 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/DbModels/FlProductDbEntity.cs
0 → 100644
| 1 | +using SqlSugar; | |
| 2 | + | |
| 3 | +namespace FoodLabeling.Application.Services.DbModels; | |
| 4 | + | |
| 5 | +[SugarTable("fl_product")] | |
| 6 | +public class FlProductDbEntity | |
| 7 | +{ | |
| 8 | + [SugarColumn(IsPrimaryKey = true)] | |
| 9 | + public string Id { get; set; } = string.Empty; | |
| 10 | + | |
| 11 | + public bool IsDeleted { get; set; } | |
| 12 | + | |
| 13 | + public string ProductCode { get; set; } = string.Empty; | |
| 14 | + | |
| 15 | + public string ProductName { get; set; } = string.Empty; | |
| 16 | + | |
| 17 | + public string? CategoryName { get; set; } | |
| 18 | + | |
| 19 | + public string? ProductImageUrl { get; set; } | |
| 20 | + | |
| 21 | + public bool State { get; set; } | |
| 22 | +} | |
| 23 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelAppService.cs
0 → 100644
| 1 | +using System.Text.Json; | |
| 2 | +using FoodLabeling.Application.Contracts.Dtos.Common; | |
| 3 | +using FoodLabeling.Application.Contracts.Dtos.Label; | |
| 4 | +using FoodLabeling.Application.Contracts.Dtos.LabelTemplate; | |
| 5 | +using FoodLabeling.Application.Contracts.IServices; | |
| 6 | +using FoodLabeling.Application.Services.DbModels; | |
| 7 | +using FoodLabeling.Domain.Entities; | |
| 8 | +using SqlSugar; | |
| 9 | +using Volo.Abp; | |
| 10 | +using Volo.Abp.Application.Services; | |
| 11 | +using Volo.Abp.Guids; | |
| 12 | +using Volo.Abp.Uow; | |
| 13 | +using Yi.Framework.SqlSugarCore.Abstractions; | |
| 14 | + | |
| 15 | +namespace FoodLabeling.Application.Services; | |
| 16 | + | |
| 17 | +/// <summary> | |
| 18 | +/// 标签管理(一个产品展示多个标签) | |
| 19 | +/// </summary> | |
| 20 | +public class LabelAppService : ApplicationService, ILabelAppService | |
| 21 | +{ | |
| 22 | + private readonly ISqlSugarDbContext _dbContext; | |
| 23 | + private readonly IGuidGenerator _guidGenerator; | |
| 24 | + | |
| 25 | + public LabelAppService(ISqlSugarDbContext dbContext, IGuidGenerator guidGenerator) | |
| 26 | + { | |
| 27 | + _dbContext = dbContext; | |
| 28 | + _guidGenerator = guidGenerator; | |
| 29 | + } | |
| 30 | + | |
| 31 | + public async Task<PagedResultWithPageDto<LabelGetListOutputDto>> GetListAsync(LabelGetListInputVo input) | |
| 32 | + { | |
| 33 | + RefAsync<int> total = 0; | |
| 34 | + | |
| 35 | + var productId = input.ProductId?.Trim(); | |
| 36 | + var locationId = input.LocationId?.Trim(); | |
| 37 | + var keyword = input.Keyword?.Trim(); | |
| 38 | + var labelCategoryId = input.LabelCategoryId?.Trim(); | |
| 39 | + var labelTypeId = input.LabelTypeId?.Trim(); | |
| 40 | + var templateCode = input.TemplateCode?.Trim(); | |
| 41 | + | |
| 42 | + // 先查 label-product 映射(按产品) | |
| 43 | + var query = _dbContext.SqlSugarClient.Queryable<FlLabelProductDbEntity, FlLabelDbEntity, FlProductDbEntity, FlLabelCategoryDbEntity, FlLabelTypeDbEntity, FlLabelTemplateDbEntity>( | |
| 44 | + (lp, l, p, c, t, tpl) => | |
| 45 | + lp.LabelId == l.Id && | |
| 46 | + lp.ProductId == p.Id && | |
| 47 | + l.LabelCategoryId == c.Id && | |
| 48 | + l.LabelTypeId == t.Id && | |
| 49 | + l.TemplateId == tpl.Id) | |
| 50 | + .Where((lp, l, p, c, t, tpl) => l.IsDeleted == false) | |
| 51 | + .Where((lp, l, p, c, t, tpl) => !c.IsDeleted) | |
| 52 | + .Where((lp, l, p, c, t, tpl) => !t.IsDeleted) | |
| 53 | + .Where((lp, l, p, c, t, tpl) => !tpl.IsDeleted) | |
| 54 | + .Where((lp, l, p, c, t, tpl) => !p.IsDeleted) | |
| 55 | + .WhereIF(!string.IsNullOrWhiteSpace(productId), (lp, l, p, c, t, tpl) => lp.ProductId == productId) | |
| 56 | + .WhereIF(!string.IsNullOrWhiteSpace(locationId), (lp, l, p, c, t, tpl) => l.LocationId == locationId) | |
| 57 | + .WhereIF(!string.IsNullOrWhiteSpace(labelCategoryId), (lp, l, p, c, t, tpl) => l.LabelCategoryId == labelCategoryId) | |
| 58 | + .WhereIF(!string.IsNullOrWhiteSpace(labelTypeId), (lp, l, p, c, t, tpl) => l.LabelTypeId == labelTypeId) | |
| 59 | + .WhereIF(!string.IsNullOrWhiteSpace(templateCode), (lp, l, p, c, t, tpl) => tpl.TemplateCode == templateCode) | |
| 60 | + .WhereIF(!string.IsNullOrWhiteSpace(keyword), | |
| 61 | + (lp, l, p, c, t, tpl) => | |
| 62 | + l.LabelName.Contains(keyword!) || | |
| 63 | + p.ProductName.Contains(keyword!) || | |
| 64 | + c.CategoryName.Contains(keyword!) || | |
| 65 | + t.TypeName.Contains(keyword!)) | |
| 66 | + .WhereIF(input.State != null, (lp, l, p, c, t, tpl) => l.State == input.State) | |
| 67 | + .OrderByDescending((lp, l, p, c, t, tpl) => l.LastModificationTime ?? l.CreationTime); | |
| 68 | + | |
| 69 | + if (!string.IsNullOrWhiteSpace(input.Sorting)) | |
| 70 | + { | |
| 71 | + query = query.OrderBy(input.Sorting); | |
| 72 | + } | |
| 73 | + | |
| 74 | + var entities = await query.Select((lp, l, p, c, t, tpl) => new | |
| 75 | + { | |
| 76 | + LabelCode = l.LabelCode, | |
| 77 | + LabelName = l.LabelName, | |
| 78 | + LocationId = l.LocationId, | |
| 79 | + LocationName = (string?)null, // later fill | |
| 80 | + LabelCategoryName = c.CategoryName, | |
| 81 | + ProductCategoryName = p.CategoryName, | |
| 82 | + ProductName = p.ProductName, | |
| 83 | + TemplateName = tpl.TemplateName, | |
| 84 | + LabelTypeName = t.TypeName, | |
| 85 | + State = l.State, | |
| 86 | + LastEdited = l.LastModificationTime ?? l.CreationTime | |
| 87 | + }) | |
| 88 | + .ToPageListAsync(input.SkipCount, input.MaxResultCount, total); | |
| 89 | + | |
| 90 | + var locationIds = entities | |
| 91 | + .Select(x => x.LocationId) | |
| 92 | + .Where(x => !string.IsNullOrWhiteSpace(x)) | |
| 93 | + .Select(x => x!.Trim()) | |
| 94 | + .Distinct() | |
| 95 | + .ToList(); | |
| 96 | + | |
| 97 | + var locationMap = new Dictionary<string, LocationAggregateRoot>(); | |
| 98 | + if (locationIds.Count > 0) | |
| 99 | + { | |
| 100 | + var locGuids = locationIds.Where(x => Guid.TryParse(x, out _)).Select(Guid.Parse).ToList(); | |
| 101 | + if (locGuids.Count > 0) | |
| 102 | + { | |
| 103 | + var locs = await _dbContext.SqlSugarClient.Queryable<LocationAggregateRoot>() | |
| 104 | + .Where(x => !x.IsDeleted) | |
| 105 | + .Where(x => locGuids.Contains(x.Id)) | |
| 106 | + .ToListAsync(); | |
| 107 | + locationMap = locs.ToDictionary(x => x.Id.ToString(), x => x); | |
| 108 | + } | |
| 109 | + } | |
| 110 | + | |
| 111 | + var items = entities.Select(x => | |
| 112 | + { | |
| 113 | + var locationName = string.Empty; | |
| 114 | + if (!string.IsNullOrWhiteSpace(x.LocationId) && locationMap.TryGetValue(x.LocationId!, out var loc)) | |
| 115 | + { | |
| 116 | + locationName = loc.LocationName ?? loc.LocationCode; | |
| 117 | + } | |
| 118 | + return new LabelGetListOutputDto | |
| 119 | + { | |
| 120 | + Id = x.LabelCode ?? string.Empty, | |
| 121 | + LabelName = x.LabelName ?? string.Empty, | |
| 122 | + LocationName = string.IsNullOrWhiteSpace(locationName) ? "无" : locationName, | |
| 123 | + LabelCategoryName = x.LabelCategoryName ?? string.Empty, | |
| 124 | + ProductCategoryName = x.ProductCategoryName ?? string.Empty, | |
| 125 | + ProductName = x.ProductName ?? string.Empty, | |
| 126 | + TemplateName = x.TemplateName ?? string.Empty, | |
| 127 | + LabelTypeName = x.LabelTypeName ?? string.Empty, | |
| 128 | + State = x.State, | |
| 129 | + LastEdited = x.LastEdited, | |
| 130 | + HasError = false | |
| 131 | + }; | |
| 132 | + }).ToList(); | |
| 133 | + | |
| 134 | + var pageSize = input.MaxResultCount <= 0 ? items.Count : input.MaxResultCount; | |
| 135 | + var pageIndex = pageSize <= 0 ? 1 : (input.SkipCount / pageSize) + 1; | |
| 136 | + var totalPages = pageSize <= 0 ? 0 : (int)Math.Ceiling(total / (double)pageSize); | |
| 137 | + | |
| 138 | + return new PagedResultWithPageDto<LabelGetListOutputDto> | |
| 139 | + { | |
| 140 | + PageIndex = pageIndex, | |
| 141 | + PageSize = pageSize, | |
| 142 | + TotalCount = total, | |
| 143 | + TotalPages = totalPages, | |
| 144 | + Items = items | |
| 145 | + }; | |
| 146 | + } | |
| 147 | + | |
| 148 | + public async Task<LabelGetOutputDto> GetAsync(string id) | |
| 149 | + { | |
| 150 | + var labelCode = id?.Trim(); | |
| 151 | + if (string.IsNullOrWhiteSpace(labelCode)) | |
| 152 | + { | |
| 153 | + throw new UserFriendlyException("标签Code不能为空"); | |
| 154 | + } | |
| 155 | + | |
| 156 | + var label = await _dbContext.SqlSugarClient.Queryable<FlLabelDbEntity>() | |
| 157 | + .FirstAsync(x => !x.IsDeleted && x.LabelCode == labelCode); | |
| 158 | + if (label is null) | |
| 159 | + { | |
| 160 | + throw new UserFriendlyException("标签不存在"); | |
| 161 | + } | |
| 162 | + | |
| 163 | + var template = await _dbContext.SqlSugarClient.Queryable<FlLabelTemplateDbEntity>() | |
| 164 | + .FirstAsync(x => x.Id == label.TemplateId); | |
| 165 | + var category = await _dbContext.SqlSugarClient.Queryable<FlLabelCategoryDbEntity>() | |
| 166 | + .FirstAsync(x => x.Id == label.LabelCategoryId); | |
| 167 | + var type = await _dbContext.SqlSugarClient.Queryable<FlLabelTypeDbEntity>() | |
| 168 | + .FirstAsync(x => x.Id == label.LabelTypeId); | |
| 169 | + | |
| 170 | + LocationAggregateRoot? location = null; | |
| 171 | + if (!string.IsNullOrWhiteSpace(label.LocationId) && Guid.TryParse(label.LocationId, out var locId)) | |
| 172 | + { | |
| 173 | + location = await _dbContext.SqlSugarClient.Queryable<LocationAggregateRoot>() | |
| 174 | + .FirstAsync(x => !x.IsDeleted && x.Id == locId); | |
| 175 | + } | |
| 176 | + | |
| 177 | + var productIds = await _dbContext.SqlSugarClient.Queryable<FlLabelProductDbEntity>() | |
| 178 | + .Where(x => x.LabelId == label.Id) | |
| 179 | + .Select(x => x.ProductId) | |
| 180 | + .ToListAsync(); | |
| 181 | + | |
| 182 | + object? labelInfo = null; | |
| 183 | + if (!string.IsNullOrWhiteSpace(label.LabelInfoJson)) | |
| 184 | + { | |
| 185 | + labelInfo = JsonSerializer.Deserialize<object>(label.LabelInfoJson); | |
| 186 | + } | |
| 187 | + | |
| 188 | + return new LabelGetOutputDto | |
| 189 | + { | |
| 190 | + Id = label.LabelCode, | |
| 191 | + LabelName = label.LabelName, | |
| 192 | + LocationId = label.LocationId ?? string.Empty, | |
| 193 | + LocationName = location?.LocationName ?? location?.LocationCode ?? "无", | |
| 194 | + LabelCategoryId = label.LabelCategoryId ?? string.Empty, | |
| 195 | + LabelCategoryName = category?.CategoryName ?? "无", | |
| 196 | + LabelTypeId = label.LabelTypeId ?? string.Empty, | |
| 197 | + LabelTypeName = type?.TypeName ?? "无", | |
| 198 | + TemplateCode = template?.TemplateCode ?? string.Empty, | |
| 199 | + TemplateName = template?.TemplateName ?? string.Empty, | |
| 200 | + State = label.State, | |
| 201 | + LabelInfoJson = labelInfo, | |
| 202 | + ProductIds = productIds | |
| 203 | + }; | |
| 204 | + } | |
| 205 | + | |
| 206 | + [UnitOfWork] | |
| 207 | + public async Task<LabelGetOutputDto> CreateAsync(LabelCreateInputVo input) | |
| 208 | + { | |
| 209 | + var labelCode = input.LabelCode?.Trim(); | |
| 210 | + if (string.IsNullOrWhiteSpace(labelCode)) | |
| 211 | + { | |
| 212 | + labelCode = $"LBL_{_guidGenerator.Create():N}"; | |
| 213 | + } | |
| 214 | + | |
| 215 | + var labelName = input.LabelName?.Trim(); | |
| 216 | + if (string.IsNullOrWhiteSpace(labelName)) | |
| 217 | + { | |
| 218 | + throw new UserFriendlyException("标签名称不能为空"); | |
| 219 | + } | |
| 220 | + | |
| 221 | + if (input.ProductIds is null || input.ProductIds.Count == 0) | |
| 222 | + { | |
| 223 | + throw new UserFriendlyException("标签至少需要绑定一个产品"); | |
| 224 | + } | |
| 225 | + | |
| 226 | + if (string.IsNullOrWhiteSpace(input.TemplateCode)) | |
| 227 | + { | |
| 228 | + throw new UserFriendlyException("模板编码不能为空"); | |
| 229 | + } | |
| 230 | + if (string.IsNullOrWhiteSpace(input.LocationId)) | |
| 231 | + { | |
| 232 | + throw new UserFriendlyException("门店Id不能为空"); | |
| 233 | + } | |
| 234 | + if (string.IsNullOrWhiteSpace(input.LabelCategoryId)) | |
| 235 | + { | |
| 236 | + throw new UserFriendlyException("标签分类Id不能为空"); | |
| 237 | + } | |
| 238 | + if (string.IsNullOrWhiteSpace(input.LabelTypeId)) | |
| 239 | + { | |
| 240 | + throw new UserFriendlyException("标签类型Id不能为空"); | |
| 241 | + } | |
| 242 | + | |
| 243 | + var template = await _dbContext.SqlSugarClient.Queryable<FlLabelTemplateDbEntity>() | |
| 244 | + .FirstAsync(x => !x.IsDeleted && x.TemplateCode == input.TemplateCode.Trim()); | |
| 245 | + if (template is null) | |
| 246 | + { | |
| 247 | + throw new UserFriendlyException("模板不存在"); | |
| 248 | + } | |
| 249 | + | |
| 250 | + // 唯一性校验(LabelCode) | |
| 251 | + var exists = await _dbContext.SqlSugarClient.Queryable<FlLabelDbEntity>() | |
| 252 | + .AnyAsync(x => !x.IsDeleted && x.LabelCode == labelCode); | |
| 253 | + if (exists) | |
| 254 | + { | |
| 255 | + throw new UserFriendlyException("标签编码已存在"); | |
| 256 | + } | |
| 257 | + | |
| 258 | + // 插入 fl_label | |
| 259 | + var now = DateTime.Now; | |
| 260 | + var labelId = _guidGenerator.Create().ToString(); | |
| 261 | + var labelEntity = new FlLabelDbEntity | |
| 262 | + { | |
| 263 | + Id = labelId, | |
| 264 | + IsDeleted = false, | |
| 265 | + CreationTime = now, | |
| 266 | + CreatorId = CurrentUser?.Id?.ToString(), | |
| 267 | + LastModifierId = CurrentUser?.Id?.ToString(), | |
| 268 | + LastModificationTime = now, | |
| 269 | + ConcurrencyStamp = string.Empty, | |
| 270 | + LabelCode = labelCode, | |
| 271 | + LabelName = labelName, | |
| 272 | + TemplateId = template.Id, | |
| 273 | + LocationId = input.LocationId?.Trim(), | |
| 274 | + LabelCategoryId = input.LabelCategoryId?.Trim(), | |
| 275 | + LabelTypeId = input.LabelTypeId?.Trim(), | |
| 276 | + State = input.State, | |
| 277 | + LabelType = null, | |
| 278 | + LabelInfoJson = input.LabelInfoJson == null ? null : JsonSerializer.Serialize(input.LabelInfoJson) | |
| 279 | + }; | |
| 280 | + await _dbContext.SqlSugarClient.Insertable(labelEntity).ExecuteCommandAsync(); | |
| 281 | + | |
| 282 | + // 插入 fl_label_product | |
| 283 | + var productIds = input.ProductIds.Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim()).Distinct().ToList(); | |
| 284 | + var rows = productIds.Select(pid => new FlLabelProductDbEntity | |
| 285 | + { | |
| 286 | + Id = _guidGenerator.Create().ToString(), | |
| 287 | + LabelId = labelId, | |
| 288 | + ProductId = pid | |
| 289 | + }).ToList(); | |
| 290 | + await _dbContext.SqlSugarClient.Insertable(rows).ExecuteCommandAsync(); | |
| 291 | + | |
| 292 | + return await GetAsync(labelCode); | |
| 293 | + } | |
| 294 | + | |
| 295 | + [UnitOfWork] | |
| 296 | + public async Task<LabelGetOutputDto> UpdateAsync(string id, LabelUpdateInputVo input) | |
| 297 | + { | |
| 298 | + var labelCode = id?.Trim(); | |
| 299 | + if (string.IsNullOrWhiteSpace(labelCode)) | |
| 300 | + { | |
| 301 | + throw new UserFriendlyException("标签Code不能为空"); | |
| 302 | + } | |
| 303 | + | |
| 304 | + var label = await _dbContext.SqlSugarClient.Queryable<FlLabelDbEntity>() | |
| 305 | + .FirstAsync(x => !x.IsDeleted && x.LabelCode == labelCode); | |
| 306 | + if (label is null) | |
| 307 | + { | |
| 308 | + throw new UserFriendlyException("标签不存在"); | |
| 309 | + } | |
| 310 | + | |
| 311 | + if (input.ProductIds is null || input.ProductIds.Count == 0) | |
| 312 | + { | |
| 313 | + throw new UserFriendlyException("标签至少需要绑定一个产品"); | |
| 314 | + } | |
| 315 | + | |
| 316 | + if (string.IsNullOrWhiteSpace(input.TemplateCode)) | |
| 317 | + { | |
| 318 | + throw new UserFriendlyException("模板编码不能为空"); | |
| 319 | + } | |
| 320 | + if (string.IsNullOrWhiteSpace(input.LocationId)) | |
| 321 | + { | |
| 322 | + throw new UserFriendlyException("门店Id不能为空"); | |
| 323 | + } | |
| 324 | + if (string.IsNullOrWhiteSpace(input.LabelCategoryId)) | |
| 325 | + { | |
| 326 | + throw new UserFriendlyException("标签分类Id不能为空"); | |
| 327 | + } | |
| 328 | + if (string.IsNullOrWhiteSpace(input.LabelTypeId)) | |
| 329 | + { | |
| 330 | + throw new UserFriendlyException("标签类型Id不能为空"); | |
| 331 | + } | |
| 332 | + | |
| 333 | + var template = await _dbContext.SqlSugarClient.Queryable<FlLabelTemplateDbEntity>() | |
| 334 | + .FirstAsync(x => !x.IsDeleted && x.TemplateCode == input.TemplateCode.Trim()); | |
| 335 | + if (template is null) | |
| 336 | + { | |
| 337 | + throw new UserFriendlyException("模板不存在"); | |
| 338 | + } | |
| 339 | + | |
| 340 | + var now = DateTime.Now; | |
| 341 | + label.LabelName = input.LabelName?.Trim() ?? label.LabelName; | |
| 342 | + label.TemplateId = template.Id; | |
| 343 | + label.LocationId = input.LocationId?.Trim(); | |
| 344 | + label.LabelCategoryId = input.LabelCategoryId?.Trim(); | |
| 345 | + label.LabelTypeId = input.LabelTypeId?.Trim(); | |
| 346 | + label.State = input.State; | |
| 347 | + label.LastModifierId = CurrentUser?.Id?.ToString(); | |
| 348 | + label.LastModificationTime = now; | |
| 349 | + label.LabelInfoJson = input.LabelInfoJson == null ? null : JsonSerializer.Serialize(input.LabelInfoJson); | |
| 350 | + | |
| 351 | + await _dbContext.SqlSugarClient.Updateable(label).ExecuteCommandAsync(); | |
| 352 | + | |
| 353 | + // 重建关联 | |
| 354 | + await _dbContext.SqlSugarClient.Deleteable<FlLabelProductDbEntity>() | |
| 355 | + .Where(x => x.LabelId == label.Id) | |
| 356 | + .ExecuteCommandAsync(); | |
| 357 | + | |
| 358 | + var productIds = input.ProductIds.Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim()).Distinct().ToList(); | |
| 359 | + var rows = productIds.Select(pid => new FlLabelProductDbEntity | |
| 360 | + { | |
| 361 | + Id = _guidGenerator.Create().ToString(), | |
| 362 | + LabelId = label.Id, | |
| 363 | + ProductId = pid | |
| 364 | + }).ToList(); | |
| 365 | + await _dbContext.SqlSugarClient.Insertable(rows).ExecuteCommandAsync(); | |
| 366 | + | |
| 367 | + return await GetAsync(labelCode); | |
| 368 | + } | |
| 369 | + | |
| 370 | + [UnitOfWork] | |
| 371 | + public async Task DeleteAsync(string id) | |
| 372 | + { | |
| 373 | + var labelCode = id?.Trim(); | |
| 374 | + if (string.IsNullOrWhiteSpace(labelCode)) | |
| 375 | + { | |
| 376 | + return; | |
| 377 | + } | |
| 378 | + | |
| 379 | + var label = await _dbContext.SqlSugarClient.Queryable<FlLabelDbEntity>() | |
| 380 | + .FirstAsync(x => !x.IsDeleted && x.LabelCode == labelCode); | |
| 381 | + if (label is null) | |
| 382 | + { | |
| 383 | + return; | |
| 384 | + } | |
| 385 | + | |
| 386 | + label.IsDeleted = true; | |
| 387 | + label.LastModifierId = CurrentUser?.Id?.ToString(); | |
| 388 | + label.LastModificationTime = DateTime.Now; | |
| 389 | + await _dbContext.SqlSugarClient.Updateable(label).ExecuteCommandAsync(); | |
| 390 | + | |
| 391 | + await _dbContext.SqlSugarClient.Deleteable<FlLabelProductDbEntity>() | |
| 392 | + .Where(x => x.LabelId == label.Id) | |
| 393 | + .ExecuteCommandAsync(); | |
| 394 | + } | |
| 395 | + | |
| 396 | + /// <summary> | |
| 397 | + /// 标签预览:不落库,只把 template elements 的 AUTO_DB/PRINT_INPUT 渲染进 config | |
| 398 | + /// </summary> | |
| 399 | + [UnitOfWork] | |
| 400 | + public async Task<LabelTemplatePreviewDto> PreviewAsync(LabelPreviewResolveInputVo input) | |
| 401 | + { | |
| 402 | + var labelCode = input?.LabelCode?.Trim(); | |
| 403 | + if (string.IsNullOrWhiteSpace(labelCode)) | |
| 404 | + { | |
| 405 | + throw new UserFriendlyException("labelCode不能为空"); | |
| 406 | + } | |
| 407 | + | |
| 408 | + var label = await _dbContext.SqlSugarClient.Queryable<FlLabelDbEntity>() | |
| 409 | + .FirstAsync(x => !x.IsDeleted && x.LabelCode == labelCode); | |
| 410 | + if (label is null) | |
| 411 | + { | |
| 412 | + throw new UserFriendlyException("标签不存在"); | |
| 413 | + } | |
| 414 | + | |
| 415 | + // 选择预览产品 | |
| 416 | + var productId = input?.ProductId?.Trim(); | |
| 417 | + if (string.IsNullOrWhiteSpace(productId)) | |
| 418 | + { | |
| 419 | + productId = await _dbContext.SqlSugarClient.Queryable<FlLabelProductDbEntity>() | |
| 420 | + .Where(x => x.LabelId == label.Id) | |
| 421 | + .Select(x => x.ProductId) | |
| 422 | + .FirstAsync(); | |
| 423 | + } | |
| 424 | + | |
| 425 | + if (string.IsNullOrWhiteSpace(productId)) | |
| 426 | + { | |
| 427 | + throw new UserFriendlyException("该标签未绑定产品,无法预览"); | |
| 428 | + } | |
| 429 | + | |
| 430 | + var product = await _dbContext.SqlSugarClient.Queryable<FlProductDbEntity>() | |
| 431 | + .FirstAsync(x => !x.IsDeleted && x.Id == productId); | |
| 432 | + if (product is null) | |
| 433 | + { | |
| 434 | + throw new UserFriendlyException("预览产品不存在"); | |
| 435 | + } | |
| 436 | + | |
| 437 | + // 取模板头 & elements | |
| 438 | + var template = await _dbContext.SqlSugarClient.Queryable<FlLabelTemplateDbEntity>() | |
| 439 | + .FirstAsync(x => !x.IsDeleted && x.Id == label.TemplateId); | |
| 440 | + if (template is null) | |
| 441 | + { | |
| 442 | + throw new UserFriendlyException("模板不存在"); | |
| 443 | + } | |
| 444 | + | |
| 445 | + var elements = await _dbContext.SqlSugarClient.Queryable<FlLabelTemplateElementDbEntity>() | |
| 446 | + .Where(x => x.TemplateId == template.Id) | |
| 447 | + // SqlSugar 不提供 ThenBy,这里用组合排序键保证 OrderNum + ZIndex 的稳定顺序 | |
| 448 | + .OrderBy(x => x.OrderNum * 1000000 + x.ZIndex) | |
| 449 | + .ToListAsync(); | |
| 450 | + | |
| 451 | + // 解析 labelInfo(可用于补充一些数值) | |
| 452 | + Dictionary<string, object?> labelInfoDict = new(); | |
| 453 | + if (!string.IsNullOrWhiteSpace(label.LabelInfoJson)) | |
| 454 | + { | |
| 455 | + try | |
| 456 | + { | |
| 457 | + labelInfoDict = JsonSerializer.Deserialize<Dictionary<string, object?>>(label.LabelInfoJson) | |
| 458 | + ?? new Dictionary<string, object?>(); | |
| 459 | + } | |
| 460 | + catch | |
| 461 | + { | |
| 462 | + // ignore | |
| 463 | + } | |
| 464 | + } | |
| 465 | + | |
| 466 | + var printInputJson = input?.PrintInputJson ?? new Dictionary<string, object?>(); | |
| 467 | + | |
| 468 | + static int TryGetInt(object? v, int defaultValue) | |
| 469 | + { | |
| 470 | + if (v is null) return defaultValue; | |
| 471 | + if (v is int i) return i; | |
| 472 | + if (v is long l) return (int)l; | |
| 473 | + if (v is decimal d) return (int)d; | |
| 474 | + if (v is double db) return (int)db; | |
| 475 | + if (v is JsonElement je) | |
| 476 | + { | |
| 477 | + if (je.ValueKind == JsonValueKind.Number && je.TryGetInt32(out var ii)) return ii; | |
| 478 | + if (je.ValueKind == JsonValueKind.String && int.TryParse(je.GetString(), out var si)) return si; | |
| 479 | + } | |
| 480 | + if (v is string s && int.TryParse(s, out var st)) return st; | |
| 481 | + return defaultValue; | |
| 482 | + } | |
| 483 | + | |
| 484 | + static string? TryToString(object? v) | |
| 485 | + { | |
| 486 | + if (v is null) return null; | |
| 487 | + if (v is string s) return s; | |
| 488 | + if (v is JsonElement je) | |
| 489 | + { | |
| 490 | + if (je.ValueKind == JsonValueKind.String) return je.GetString(); | |
| 491 | + if (je.ValueKind == JsonValueKind.Number || je.ValueKind == JsonValueKind.True || je.ValueKind == JsonValueKind.False) | |
| 492 | + { | |
| 493 | + return je.ToString(); | |
| 494 | + } | |
| 495 | + } | |
| 496 | + return v.ToString(); | |
| 497 | + } | |
| 498 | + | |
| 499 | + static void UpsertConfigValue(Dictionary<string, object?> cfg, string key, object? value) | |
| 500 | + { | |
| 501 | + if (cfg.ContainsKey(key)) | |
| 502 | + { | |
| 503 | + cfg[key] = value; | |
| 504 | + return; | |
| 505 | + } | |
| 506 | + cfg.Add(key, value); | |
| 507 | + } | |
| 508 | + | |
| 509 | + Dictionary<string, object?> ParseConfig(string? configJson) | |
| 510 | + { | |
| 511 | + if (string.IsNullOrWhiteSpace(configJson)) | |
| 512 | + { | |
| 513 | + return new Dictionary<string, object?>(); | |
| 514 | + } | |
| 515 | + | |
| 516 | + try | |
| 517 | + { | |
| 518 | + return JsonSerializer.Deserialize<Dictionary<string, object?>>(configJson) | |
| 519 | + ?? new Dictionary<string, object?>(); | |
| 520 | + } | |
| 521 | + catch | |
| 522 | + { | |
| 523 | + return new Dictionary<string, object?>(); | |
| 524 | + } | |
| 525 | + } | |
| 526 | + | |
| 527 | + foreach (var el in elements) | |
| 528 | + { | |
| 529 | + // FIXED:不处理(直接保留 config) | |
| 530 | + // AUTO_DB:根据 type 做一个最小可用渲染(支持 TEXT_PRODUCT / BARCODE / QRCODE / DATE / TIME) | |
| 531 | + // PRINT_INPUT:按 InputKey 覆盖相应字段(优先级最高) | |
| 532 | + } | |
| 533 | + | |
| 534 | + var resolvedElements = elements.Select(el => | |
| 535 | + { | |
| 536 | + var cfg = ParseConfig(el.ConfigJson); | |
| 537 | + | |
| 538 | + // 1) 先做 AUTO_DB:按类型兜底填充 | |
| 539 | + if (string.Equals(el.ValueSourceType, "AUTO_DB", StringComparison.OrdinalIgnoreCase)) | |
| 540 | + { | |
| 541 | + switch (el.ElementType) | |
| 542 | + { | |
| 543 | + case "TEXT_PRODUCT": | |
| 544 | + UpsertConfigValue(cfg, "text", product.ProductName); | |
| 545 | + break; | |
| 546 | + case "TEXT_PRICE": | |
| 547 | + { | |
| 548 | + // price 可能在 labelInfo 或 printInput 里 | |
| 549 | + object? priceObj = null; | |
| 550 | + if (labelInfoDict.TryGetValue("price", out var p)) priceObj = p; | |
| 551 | + if (priceObj is null && printInputJson.TryGetValue("price", out var pp)) priceObj = pp; | |
| 552 | + var priceStr = TryToString(priceObj); | |
| 553 | + if (!string.IsNullOrWhiteSpace(priceStr)) | |
| 554 | + { | |
| 555 | + UpsertConfigValue(cfg, "text", priceStr); | |
| 556 | + } | |
| 557 | + } | |
| 558 | + break; | |
| 559 | + case "BARCODE": | |
| 560 | + if (!string.IsNullOrWhiteSpace(product.ProductCode)) | |
| 561 | + { | |
| 562 | + UpsertConfigValue(cfg, "data", product.ProductCode); | |
| 563 | + } | |
| 564 | + break; | |
| 565 | + case "QRCODE": | |
| 566 | + if (!string.IsNullOrWhiteSpace(product.ProductCode)) | |
| 567 | + { | |
| 568 | + UpsertConfigValue(cfg, "data", product.ProductCode); | |
| 569 | + } | |
| 570 | + break; | |
| 571 | + case "DATE": | |
| 572 | + { | |
| 573 | + var offsetDays = cfg.TryGetValue("offsetDays", out var od) ? TryGetInt(od, 0) : 0; | |
| 574 | + var dt = DateTime.Today.AddDays(offsetDays); | |
| 575 | + UpsertConfigValue(cfg, "format", dt.ToString("yyyy-MM-dd")); | |
| 576 | + cfg.Remove("inputType"); | |
| 577 | + } | |
| 578 | + break; | |
| 579 | + case "TIME": | |
| 580 | + { | |
| 581 | + var dt = DateTime.Now; | |
| 582 | + UpsertConfigValue(cfg, "format", dt.ToString("HH:mm")); | |
| 583 | + cfg.Remove("inputType"); | |
| 584 | + } | |
| 585 | + break; | |
| 586 | + } | |
| 587 | + } | |
| 588 | + | |
| 589 | + // 2) 再做 PRINT_INPUT:按 InputKey 覆盖(如果前端传了) | |
| 590 | + if (string.Equals(el.ValueSourceType, "PRINT_INPUT", StringComparison.OrdinalIgnoreCase) | |
| 591 | + && !string.IsNullOrWhiteSpace(el.InputKey) | |
| 592 | + && printInputJson.TryGetValue(el.InputKey!, out var inputValue)) | |
| 593 | + { | |
| 594 | + var s = TryToString(inputValue); | |
| 595 | + if (!string.IsNullOrWhiteSpace(s)) | |
| 596 | + { | |
| 597 | + switch (el.ElementType) | |
| 598 | + { | |
| 599 | + case "TEXT_STATIC": | |
| 600 | + case "TEXT_PRODUCT": | |
| 601 | + case "TEXT_PRICE": | |
| 602 | + UpsertConfigValue(cfg, "text", s); | |
| 603 | + cfg.Remove("inputType"); | |
| 604 | + break; | |
| 605 | + case "BARCODE": | |
| 606 | + case "QRCODE": | |
| 607 | + UpsertConfigValue(cfg, "data", s); | |
| 608 | + break; | |
| 609 | + case "DATE": | |
| 610 | + case "TIME": | |
| 611 | + UpsertConfigValue(cfg, "format", s); | |
| 612 | + cfg.Remove("inputType"); | |
| 613 | + break; | |
| 614 | + } | |
| 615 | + } | |
| 616 | + } | |
| 617 | + | |
| 618 | + // 3) FIXED:不做任何覆盖,保持模板/标签设计时写入的固定值(由前端/设计器落库) | |
| 619 | + | |
| 620 | + return new LabelTemplateElementDto | |
| 621 | + { | |
| 622 | + Id = el.ElementKey, | |
| 623 | + ElementType = el.ElementType, | |
| 624 | + PosX = el.PosX, | |
| 625 | + PosY = el.PosY, | |
| 626 | + Width = el.Width, | |
| 627 | + Height = el.Height, | |
| 628 | + Rotation = string.IsNullOrWhiteSpace(el.Rotation) ? "horizontal" : el.Rotation, | |
| 629 | + BorderType = string.IsNullOrWhiteSpace(el.BorderType) ? "none" : el.BorderType, | |
| 630 | + ZIndex = el.ZIndex, | |
| 631 | + OrderNum = el.OrderNum, | |
| 632 | + ValueSourceType = el.ValueSourceType, | |
| 633 | + BindingExpr = el.BindingExpr, | |
| 634 | + AutoQueryKey = el.AutoQueryKey, | |
| 635 | + InputKey = el.InputKey, | |
| 636 | + IsRequiredInput = el.IsRequiredInput, | |
| 637 | + ConfigJson = cfg | |
| 638 | + }; | |
| 639 | + }).ToList(); | |
| 640 | + | |
| 641 | + return new LabelTemplatePreviewDto | |
| 642 | + { | |
| 643 | + Id = template.TemplateCode, | |
| 644 | + Name = template.TemplateName, | |
| 645 | + LabelType = template.LabelType ?? string.Empty, | |
| 646 | + Unit = template.Unit, | |
| 647 | + Width = template.Width, | |
| 648 | + Height = template.Height, | |
| 649 | + AppliedLocation = template.AppliedLocationType, | |
| 650 | + ShowRuler = template.ShowRuler, | |
| 651 | + ShowGrid = template.ShowGrid, | |
| 652 | + Elements = resolvedElements | |
| 653 | + }; | |
| 654 | + } | |
| 655 | +} | |
| 656 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelCategoryAppService.cs
0 → 100644
| 1 | +using FoodLabeling.Application.Contracts.Dtos.Common; | |
| 2 | +using FoodLabeling.Application.Contracts.Dtos.LabelCategory; | |
| 3 | +using FoodLabeling.Application.Contracts.IServices; | |
| 4 | +using FoodLabeling.Application.Services.DbModels; | |
| 5 | +using SqlSugar; | |
| 6 | +using Volo.Abp; | |
| 7 | +using Volo.Abp.Application.Services; | |
| 8 | +using Volo.Abp.Guids; | |
| 9 | +using Yi.Framework.SqlSugarCore.Abstractions; | |
| 10 | + | |
| 11 | +namespace FoodLabeling.Application.Services; | |
| 12 | + | |
| 13 | +public class LabelCategoryAppService : ApplicationService, ILabelCategoryAppService | |
| 14 | +{ | |
| 15 | + private readonly ISqlSugarDbContext _dbContext; | |
| 16 | + private readonly IGuidGenerator _guidGenerator; | |
| 17 | + | |
| 18 | + public LabelCategoryAppService(ISqlSugarDbContext dbContext, IGuidGenerator guidGenerator) | |
| 19 | + { | |
| 20 | + _dbContext = dbContext; | |
| 21 | + _guidGenerator = guidGenerator; | |
| 22 | + } | |
| 23 | + | |
| 24 | + public async Task<PagedResultWithPageDto<LabelCategoryGetListOutputDto>> GetListAsync(LabelCategoryGetListInputVo input) | |
| 25 | + { | |
| 26 | + RefAsync<int> total = 0; | |
| 27 | + var keyword = input.Keyword?.Trim(); | |
| 28 | + | |
| 29 | + var query = _dbContext.SqlSugarClient.Queryable<FlLabelCategoryDbEntity>() | |
| 30 | + .Where(x => !x.IsDeleted) | |
| 31 | + .WhereIF(!string.IsNullOrWhiteSpace(keyword), | |
| 32 | + x => x.CategoryCode.Contains(keyword!) || x.CategoryName.Contains(keyword!)) | |
| 33 | + .WhereIF(input.State != null, x => x.State == input.State); | |
| 34 | + | |
| 35 | + if (!string.IsNullOrWhiteSpace(input.Sorting)) | |
| 36 | + { | |
| 37 | + query = query.OrderBy(input.Sorting); | |
| 38 | + } | |
| 39 | + else | |
| 40 | + { | |
| 41 | + query = query.OrderByDescending(x => x.OrderNum).OrderByDescending(x => x.CreationTime); | |
| 42 | + } | |
| 43 | + | |
| 44 | + var entities = await query.ToPageListAsync(input.SkipCount, input.MaxResultCount, total); | |
| 45 | + var ids = entities.Select(x => x.Id).ToList(); | |
| 46 | + | |
| 47 | + var countRows = await _dbContext.SqlSugarClient.Queryable<FlLabelDbEntity>() | |
| 48 | + .Where(x => !x.IsDeleted) | |
| 49 | + .Where(x => x.LabelCategoryId != null && ids.Contains(x.LabelCategoryId)) | |
| 50 | + .GroupBy(x => x.LabelCategoryId) | |
| 51 | + .Select(x => new { CategoryId = x.LabelCategoryId, Count = SqlFunc.AggregateCount(x.Id) }) | |
| 52 | + .ToListAsync(); | |
| 53 | + var countMap = countRows.ToDictionary(x => x.CategoryId!, x => (long)x.Count); | |
| 54 | + | |
| 55 | + var items = entities.Select(x => new LabelCategoryGetListOutputDto | |
| 56 | + { | |
| 57 | + Id = x.Id, | |
| 58 | + CategoryCode = x.CategoryCode, | |
| 59 | + CategoryName = x.CategoryName, | |
| 60 | + CategoryPhotoUrl = x.CategoryPhotoUrl, | |
| 61 | + State = x.State, | |
| 62 | + OrderNum = x.OrderNum, | |
| 63 | + NoOfLabels = countMap.TryGetValue(x.Id, out var count) ? count : 0, | |
| 64 | + LastEdited = x.LastModificationTime ?? x.CreationTime | |
| 65 | + }).ToList(); | |
| 66 | + | |
| 67 | + return BuildPagedResult(input.SkipCount, input.MaxResultCount, total, items); | |
| 68 | + } | |
| 69 | + | |
| 70 | + public async Task<LabelCategoryGetOutputDto> GetAsync(string id) | |
| 71 | + { | |
| 72 | + var entity = await _dbContext.SqlSugarClient.Queryable<FlLabelCategoryDbEntity>() | |
| 73 | + .FirstAsync(x => x.Id == id && !x.IsDeleted); | |
| 74 | + if (entity is null) | |
| 75 | + { | |
| 76 | + throw new UserFriendlyException("标签分类不存在"); | |
| 77 | + } | |
| 78 | + | |
| 79 | + return MapToGetOutput(entity); | |
| 80 | + } | |
| 81 | + | |
| 82 | + public async Task<LabelCategoryGetOutputDto> CreateAsync(LabelCategoryCreateInputVo input) | |
| 83 | + { | |
| 84 | + var code = input.CategoryCode?.Trim(); | |
| 85 | + var name = input.CategoryName?.Trim(); | |
| 86 | + if (string.IsNullOrWhiteSpace(code) || string.IsNullOrWhiteSpace(name)) | |
| 87 | + { | |
| 88 | + throw new UserFriendlyException("分类编码和名称不能为空"); | |
| 89 | + } | |
| 90 | + | |
| 91 | + var duplicated = await _dbContext.SqlSugarClient.Queryable<FlLabelCategoryDbEntity>() | |
| 92 | + .AnyAsync(x => !x.IsDeleted && (x.CategoryCode == code || x.CategoryName == name)); | |
| 93 | + if (duplicated) | |
| 94 | + { | |
| 95 | + throw new UserFriendlyException("分类编码或名称已存在"); | |
| 96 | + } | |
| 97 | + | |
| 98 | + var entity = new FlLabelCategoryDbEntity | |
| 99 | + { | |
| 100 | + Id = _guidGenerator.Create().ToString(), | |
| 101 | + CategoryCode = code, | |
| 102 | + CategoryName = name, | |
| 103 | + CategoryPhotoUrl = input.CategoryPhotoUrl?.Trim(), | |
| 104 | + State = input.State, | |
| 105 | + OrderNum = input.OrderNum | |
| 106 | + }; | |
| 107 | + | |
| 108 | + await _dbContext.SqlSugarClient.Insertable(entity).ExecuteCommandAsync(); | |
| 109 | + return await GetAsync(entity.Id); | |
| 110 | + } | |
| 111 | + | |
| 112 | + public async Task<LabelCategoryGetOutputDto> UpdateAsync(string id, LabelCategoryUpdateInputVo input) | |
| 113 | + { | |
| 114 | + var entity = await _dbContext.SqlSugarClient.Queryable<FlLabelCategoryDbEntity>() | |
| 115 | + .FirstAsync(x => x.Id == id && !x.IsDeleted); | |
| 116 | + if (entity is null) | |
| 117 | + { | |
| 118 | + throw new UserFriendlyException("标签分类不存在"); | |
| 119 | + } | |
| 120 | + | |
| 121 | + var code = input.CategoryCode?.Trim(); | |
| 122 | + var name = input.CategoryName?.Trim(); | |
| 123 | + if (string.IsNullOrWhiteSpace(code) || string.IsNullOrWhiteSpace(name)) | |
| 124 | + { | |
| 125 | + throw new UserFriendlyException("分类编码和名称不能为空"); | |
| 126 | + } | |
| 127 | + | |
| 128 | + var duplicated = await _dbContext.SqlSugarClient.Queryable<FlLabelCategoryDbEntity>() | |
| 129 | + .AnyAsync(x => !x.IsDeleted && x.Id != id && (x.CategoryCode == code || x.CategoryName == name)); | |
| 130 | + if (duplicated) | |
| 131 | + { | |
| 132 | + throw new UserFriendlyException("分类编码或名称已存在"); | |
| 133 | + } | |
| 134 | + | |
| 135 | + entity.CategoryCode = code; | |
| 136 | + entity.CategoryName = name; | |
| 137 | + entity.CategoryPhotoUrl = input.CategoryPhotoUrl?.Trim(); | |
| 138 | + entity.State = input.State; | |
| 139 | + entity.OrderNum = input.OrderNum; | |
| 140 | + entity.LastModificationTime = DateTime.Now; | |
| 141 | + entity.LastModifierId = CurrentUser?.Id?.ToString(); | |
| 142 | + | |
| 143 | + await _dbContext.SqlSugarClient.Updateable(entity).ExecuteCommandAsync(); | |
| 144 | + return await GetAsync(id); | |
| 145 | + } | |
| 146 | + | |
| 147 | + public async Task DeleteAsync(string id) | |
| 148 | + { | |
| 149 | + var entity = await _dbContext.SqlSugarClient.Queryable<FlLabelCategoryDbEntity>() | |
| 150 | + .FirstAsync(x => x.Id == id && !x.IsDeleted); | |
| 151 | + if (entity is null) | |
| 152 | + { | |
| 153 | + return; | |
| 154 | + } | |
| 155 | + | |
| 156 | + var used = await _dbContext.SqlSugarClient.Queryable<FlLabelDbEntity>() | |
| 157 | + .AnyAsync(x => !x.IsDeleted && x.LabelCategoryId == id); | |
| 158 | + if (used) | |
| 159 | + { | |
| 160 | + throw new UserFriendlyException("该标签分类已被标签引用,无法删除"); | |
| 161 | + } | |
| 162 | + | |
| 163 | + entity.IsDeleted = true; | |
| 164 | + entity.LastModificationTime = DateTime.Now; | |
| 165 | + entity.LastModifierId = CurrentUser?.Id?.ToString(); | |
| 166 | + await _dbContext.SqlSugarClient.Updateable(entity).ExecuteCommandAsync(); | |
| 167 | + } | |
| 168 | + | |
| 169 | + private static LabelCategoryGetOutputDto MapToGetOutput(FlLabelCategoryDbEntity x) | |
| 170 | + { | |
| 171 | + return new LabelCategoryGetOutputDto | |
| 172 | + { | |
| 173 | + Id = x.Id, | |
| 174 | + CategoryCode = x.CategoryCode, | |
| 175 | + CategoryName = x.CategoryName, | |
| 176 | + CategoryPhotoUrl = x.CategoryPhotoUrl, | |
| 177 | + State = x.State, | |
| 178 | + OrderNum = x.OrderNum | |
| 179 | + }; | |
| 180 | + } | |
| 181 | + | |
| 182 | + private static PagedResultWithPageDto<T> BuildPagedResult<T>(int skipCount, int maxResultCount, int total, List<T> items) | |
| 183 | + { | |
| 184 | + var pageSize = maxResultCount <= 0 ? items.Count : maxResultCount; | |
| 185 | + var pageIndex = pageSize <= 0 ? 1 : (skipCount / pageSize) + 1; | |
| 186 | + var totalPages = pageSize <= 0 ? 0 : (int)Math.Ceiling(total / (double)pageSize); | |
| 187 | + return new PagedResultWithPageDto<T> | |
| 188 | + { | |
| 189 | + PageIndex = pageIndex, | |
| 190 | + PageSize = pageSize, | |
| 191 | + TotalCount = total, | |
| 192 | + TotalPages = totalPages, | |
| 193 | + Items = items | |
| 194 | + }; | |
| 195 | + } | |
| 196 | +} | |
| 197 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelMultipleOptionAppService.cs
0 → 100644
| 1 | +using FoodLabeling.Application.Contracts.Dtos.Common; | |
| 2 | +using FoodLabeling.Application.Contracts.Dtos.LabelMultipleOption; | |
| 3 | +using FoodLabeling.Application.Contracts.IServices; | |
| 4 | +using FoodLabeling.Application.Services.DbModels; | |
| 5 | +using SqlSugar; | |
| 6 | +using Volo.Abp; | |
| 7 | +using Volo.Abp.Application.Services; | |
| 8 | +using Volo.Abp.Guids; | |
| 9 | +using Yi.Framework.SqlSugarCore.Abstractions; | |
| 10 | + | |
| 11 | +namespace FoodLabeling.Application.Services; | |
| 12 | + | |
| 13 | +public class LabelMultipleOptionAppService : ApplicationService, ILabelMultipleOptionAppService | |
| 14 | +{ | |
| 15 | + private readonly ISqlSugarDbContext _dbContext; | |
| 16 | + private readonly IGuidGenerator _guidGenerator; | |
| 17 | + | |
| 18 | + public LabelMultipleOptionAppService(ISqlSugarDbContext dbContext, IGuidGenerator guidGenerator) | |
| 19 | + { | |
| 20 | + _dbContext = dbContext; | |
| 21 | + _guidGenerator = guidGenerator; | |
| 22 | + } | |
| 23 | + | |
| 24 | + public async Task<PagedResultWithPageDto<LabelMultipleOptionGetListOutputDto>> GetListAsync(LabelMultipleOptionGetListInputVo input) | |
| 25 | + { | |
| 26 | + RefAsync<int> total = 0; | |
| 27 | + var keyword = input.Keyword?.Trim(); | |
| 28 | + | |
| 29 | + var query = _dbContext.SqlSugarClient.Queryable<FlLabelMultipleOptionDbEntity>() | |
| 30 | + .Where(x => !x.IsDeleted) | |
| 31 | + .WhereIF(!string.IsNullOrWhiteSpace(keyword), x => x.OptionCode.Contains(keyword!) || x.OptionName.Contains(keyword!)) | |
| 32 | + .WhereIF(input.State != null, x => x.State == input.State); | |
| 33 | + | |
| 34 | + if (!string.IsNullOrWhiteSpace(input.Sorting)) | |
| 35 | + { | |
| 36 | + query = query.OrderBy(input.Sorting); | |
| 37 | + } | |
| 38 | + else | |
| 39 | + { | |
| 40 | + query = query.OrderByDescending(x => x.OrderNum).OrderByDescending(x => x.CreationTime); | |
| 41 | + } | |
| 42 | + | |
| 43 | + var entities = await query.ToPageListAsync(input.SkipCount, input.MaxResultCount, total); | |
| 44 | + var items = entities.Select(x => new LabelMultipleOptionGetListOutputDto | |
| 45 | + { | |
| 46 | + Id = x.Id, | |
| 47 | + OptionCode = x.OptionCode, | |
| 48 | + OptionName = x.OptionName, | |
| 49 | + OptionValuesJson = x.OptionValuesJson, | |
| 50 | + State = x.State, | |
| 51 | + OrderNum = x.OrderNum, | |
| 52 | + LastEdited = x.LastModificationTime ?? x.CreationTime | |
| 53 | + }).ToList(); | |
| 54 | + | |
| 55 | + return BuildPagedResult(input.SkipCount, input.MaxResultCount, total, items); | |
| 56 | + } | |
| 57 | + | |
| 58 | + public async Task<LabelMultipleOptionGetOutputDto> GetAsync(string id) | |
| 59 | + { | |
| 60 | + var entity = await _dbContext.SqlSugarClient.Queryable<FlLabelMultipleOptionDbEntity>() | |
| 61 | + .FirstAsync(x => x.Id == id && !x.IsDeleted); | |
| 62 | + if (entity is null) | |
| 63 | + { | |
| 64 | + throw new UserFriendlyException("多选项不存在"); | |
| 65 | + } | |
| 66 | + | |
| 67 | + return new LabelMultipleOptionGetOutputDto | |
| 68 | + { | |
| 69 | + Id = entity.Id, | |
| 70 | + OptionCode = entity.OptionCode, | |
| 71 | + OptionName = entity.OptionName, | |
| 72 | + OptionValuesJson = entity.OptionValuesJson, | |
| 73 | + State = entity.State, | |
| 74 | + OrderNum = entity.OrderNum | |
| 75 | + }; | |
| 76 | + } | |
| 77 | + | |
| 78 | + public async Task<LabelMultipleOptionGetOutputDto> CreateAsync(LabelMultipleOptionCreateInputVo input) | |
| 79 | + { | |
| 80 | + var code = input.OptionCode?.Trim(); | |
| 81 | + var name = input.OptionName?.Trim(); | |
| 82 | + if (string.IsNullOrWhiteSpace(code) || string.IsNullOrWhiteSpace(name)) | |
| 83 | + { | |
| 84 | + throw new UserFriendlyException("多选项编码和名称不能为空"); | |
| 85 | + } | |
| 86 | + | |
| 87 | + var duplicated = await _dbContext.SqlSugarClient.Queryable<FlLabelMultipleOptionDbEntity>() | |
| 88 | + .AnyAsync(x => !x.IsDeleted && (x.OptionCode == code || x.OptionName == name)); | |
| 89 | + if (duplicated) | |
| 90 | + { | |
| 91 | + throw new UserFriendlyException("多选项编码或名称已存在"); | |
| 92 | + } | |
| 93 | + | |
| 94 | + var entity = new FlLabelMultipleOptionDbEntity | |
| 95 | + { | |
| 96 | + Id = _guidGenerator.Create().ToString(), | |
| 97 | + OptionCode = code, | |
| 98 | + OptionName = name, | |
| 99 | + OptionValuesJson = input.OptionValuesJson?.Trim(), | |
| 100 | + State = input.State, | |
| 101 | + OrderNum = input.OrderNum | |
| 102 | + }; | |
| 103 | + | |
| 104 | + await _dbContext.SqlSugarClient.Insertable(entity).ExecuteCommandAsync(); | |
| 105 | + return await GetAsync(entity.Id); | |
| 106 | + } | |
| 107 | + | |
| 108 | + public async Task<LabelMultipleOptionGetOutputDto> UpdateAsync(string id, LabelMultipleOptionUpdateInputVo input) | |
| 109 | + { | |
| 110 | + var entity = await _dbContext.SqlSugarClient.Queryable<FlLabelMultipleOptionDbEntity>() | |
| 111 | + .FirstAsync(x => x.Id == id && !x.IsDeleted); | |
| 112 | + if (entity is null) | |
| 113 | + { | |
| 114 | + throw new UserFriendlyException("多选项不存在"); | |
| 115 | + } | |
| 116 | + | |
| 117 | + var code = input.OptionCode?.Trim(); | |
| 118 | + var name = input.OptionName?.Trim(); | |
| 119 | + if (string.IsNullOrWhiteSpace(code) || string.IsNullOrWhiteSpace(name)) | |
| 120 | + { | |
| 121 | + throw new UserFriendlyException("多选项编码和名称不能为空"); | |
| 122 | + } | |
| 123 | + | |
| 124 | + var duplicated = await _dbContext.SqlSugarClient.Queryable<FlLabelMultipleOptionDbEntity>() | |
| 125 | + .AnyAsync(x => !x.IsDeleted && x.Id != id && (x.OptionCode == code || x.OptionName == name)); | |
| 126 | + if (duplicated) | |
| 127 | + { | |
| 128 | + throw new UserFriendlyException("多选项编码或名称已存在"); | |
| 129 | + } | |
| 130 | + | |
| 131 | + entity.OptionCode = code; | |
| 132 | + entity.OptionName = name; | |
| 133 | + entity.OptionValuesJson = input.OptionValuesJson?.Trim(); | |
| 134 | + entity.State = input.State; | |
| 135 | + entity.OrderNum = input.OrderNum; | |
| 136 | + entity.LastModificationTime = DateTime.Now; | |
| 137 | + entity.LastModifierId = CurrentUser?.Id?.ToString(); | |
| 138 | + | |
| 139 | + await _dbContext.SqlSugarClient.Updateable(entity).ExecuteCommandAsync(); | |
| 140 | + return await GetAsync(id); | |
| 141 | + } | |
| 142 | + | |
| 143 | + public async Task DeleteAsync(string id) | |
| 144 | + { | |
| 145 | + var entity = await _dbContext.SqlSugarClient.Queryable<FlLabelMultipleOptionDbEntity>() | |
| 146 | + .FirstAsync(x => x.Id == id && !x.IsDeleted); | |
| 147 | + if (entity is null) | |
| 148 | + { | |
| 149 | + return; | |
| 150 | + } | |
| 151 | + | |
| 152 | + entity.IsDeleted = true; | |
| 153 | + entity.LastModificationTime = DateTime.Now; | |
| 154 | + entity.LastModifierId = CurrentUser?.Id?.ToString(); | |
| 155 | + await _dbContext.SqlSugarClient.Updateable(entity).ExecuteCommandAsync(); | |
| 156 | + } | |
| 157 | + | |
| 158 | + private static PagedResultWithPageDto<T> BuildPagedResult<T>(int skipCount, int maxResultCount, int total, List<T> items) | |
| 159 | + { | |
| 160 | + var pageSize = maxResultCount <= 0 ? items.Count : maxResultCount; | |
| 161 | + var pageIndex = pageSize <= 0 ? 1 : (skipCount / pageSize) + 1; | |
| 162 | + var totalPages = pageSize <= 0 ? 0 : (int)Math.Ceiling(total / (double)pageSize); | |
| 163 | + return new PagedResultWithPageDto<T> | |
| 164 | + { | |
| 165 | + PageIndex = pageIndex, | |
| 166 | + PageSize = pageSize, | |
| 167 | + TotalCount = total, | |
| 168 | + TotalPages = totalPages, | |
| 169 | + Items = items | |
| 170 | + }; | |
| 171 | + } | |
| 172 | +} | |
| 173 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelTemplateAppService.cs
0 → 100644
| 1 | +using System.Text.Json; | |
| 2 | +using FoodLabeling.Application.Contracts.Dtos.Common; | |
| 3 | +using FoodLabeling.Application.Contracts.Dtos.LabelTemplate; | |
| 4 | +using FoodLabeling.Application.Contracts.IServices; | |
| 5 | +using FoodLabeling.Application.Services.DbModels; | |
| 6 | +using FoodLabeling.Domain.Entities; | |
| 7 | +using SqlSugar; | |
| 8 | +using Volo.Abp; | |
| 9 | +using Volo.Abp.Application.Services; | |
| 10 | +using Volo.Abp.Guids; | |
| 11 | +using Volo.Abp.Uow; | |
| 12 | +using Yi.Framework.SqlSugarCore.Abstractions; | |
| 13 | + | |
| 14 | +namespace FoodLabeling.Application.Services; | |
| 15 | + | |
| 16 | +/// <summary> | |
| 17 | +/// 标签模板管理(Label Templates) | |
| 18 | +/// </summary> | |
| 19 | +public class LabelTemplateAppService : ApplicationService, ILabelTemplateAppService | |
| 20 | +{ | |
| 21 | + private readonly ISqlSugarDbContext _dbContext; | |
| 22 | + private readonly IGuidGenerator _guidGenerator; | |
| 23 | + | |
| 24 | + public LabelTemplateAppService(ISqlSugarDbContext dbContext, IGuidGenerator guidGenerator) | |
| 25 | + { | |
| 26 | + _dbContext = dbContext; | |
| 27 | + _guidGenerator = guidGenerator; | |
| 28 | + } | |
| 29 | + | |
| 30 | + public async Task<PagedResultWithPageDto<LabelTemplateGetListOutputDto>> GetListAsync(LabelTemplateGetListInputVo input) | |
| 31 | + { | |
| 32 | + RefAsync<int> total = 0; | |
| 33 | + var keyword = input.Keyword?.Trim(); | |
| 34 | + var locationId = input.LocationId?.Trim(); | |
| 35 | + var specifiedTemplateIds = new HashSet<string>(); | |
| 36 | + | |
| 37 | + if (!string.IsNullOrWhiteSpace(locationId)) | |
| 38 | + { | |
| 39 | + var rows = await _dbContext.SqlSugarClient.Queryable<FlLabelTemplateLocationDbEntity>() | |
| 40 | + .Where(x => x.LocationId == locationId) | |
| 41 | + .Select(x => x.TemplateId) | |
| 42 | + .ToListAsync(); | |
| 43 | + | |
| 44 | + specifiedTemplateIds = rows.ToHashSet(); | |
| 45 | + } | |
| 46 | + | |
| 47 | + var query = _dbContext.SqlSugarClient.Queryable<FlLabelTemplateDbEntity>() | |
| 48 | + .Where(x => !x.IsDeleted) | |
| 49 | + .WhereIF(!string.IsNullOrWhiteSpace(keyword), x => | |
| 50 | + x.TemplateName.Contains(keyword!) || x.TemplateCode.Contains(keyword!)) | |
| 51 | + .WhereIF(!string.IsNullOrWhiteSpace(input.LabelType), x => x.LabelType == input.LabelType) | |
| 52 | + .WhereIF(input.State != null, x => x.State == input.State); | |
| 53 | + | |
| 54 | + if (!string.IsNullOrWhiteSpace(locationId)) | |
| 55 | + { | |
| 56 | + query = query.Where(x => x.AppliedLocationType == "ALL" || specifiedTemplateIds.Contains(x.Id)); | |
| 57 | + } | |
| 58 | + | |
| 59 | + query = !string.IsNullOrWhiteSpace(input.Sorting) | |
| 60 | + ? query.OrderBy(input.Sorting) | |
| 61 | + : query.OrderByDescending(x => x.LastModificationTime ?? x.CreationTime); | |
| 62 | + | |
| 63 | + var pageEntities = await query.ToPageListAsync(input.SkipCount, input.MaxResultCount, total); | |
| 64 | + var templateIds = pageEntities.Select(x => x.Id).ToList(); | |
| 65 | + | |
| 66 | + // element count (Contents) | |
| 67 | + var elementCounts = await _dbContext.SqlSugarClient.Queryable<FlLabelTemplateElementDbEntity>() | |
| 68 | + .Where(x => templateIds.Contains(x.TemplateId)) | |
| 69 | + .GroupBy(x => x.TemplateId) | |
| 70 | + .Select(x => new { TemplateId = x.TemplateId, Count = SqlFunc.AggregateCount(x.Id) }) | |
| 71 | + .ToListAsync(); | |
| 72 | + var elementCountMap = elementCounts.ToDictionary(x => x.TemplateId, x => (int)x.Count); | |
| 73 | + | |
| 74 | + // applied locations (for LocationText) | |
| 75 | + var templateLocationRows = await _dbContext.SqlSugarClient.Queryable<FlLabelTemplateLocationDbEntity>() | |
| 76 | + .Where(x => templateIds.Contains(x.TemplateId)) | |
| 77 | + .ToListAsync(); | |
| 78 | + | |
| 79 | + var locationIdSet = templateLocationRows.Select(x => x.LocationId).Where(x => !string.IsNullOrWhiteSpace(x)).Distinct().ToList(); | |
| 80 | + var locationGuidList = locationIdSet | |
| 81 | + .Where(x => Guid.TryParse(x, out _)) | |
| 82 | + .Select(Guid.Parse) | |
| 83 | + .Distinct() | |
| 84 | + .ToList(); | |
| 85 | + | |
| 86 | + var locationMap = new Dictionary<Guid, LocationAggregateRoot>(); | |
| 87 | + if (locationGuidList.Count > 0) | |
| 88 | + { | |
| 89 | + var locations = await _dbContext.SqlSugarClient.Queryable<LocationAggregateRoot>() | |
| 90 | + .Where(x => !x.IsDeleted) | |
| 91 | + .Where(x => locationGuidList.Contains(x.Id)) | |
| 92 | + .ToListAsync(); | |
| 93 | + locationMap = locations.ToDictionary(x => x.Id, x => x); | |
| 94 | + } | |
| 95 | + | |
| 96 | + string GetFirstLocationName(string templateDbId) | |
| 97 | + { | |
| 98 | + var first = templateLocationRows.FirstOrDefault(x => x.TemplateId == templateDbId); | |
| 99 | + if (first is null) return "Specified"; | |
| 100 | + if (Guid.TryParse(first.LocationId, out var gid) && locationMap.TryGetValue(gid, out var loc)) | |
| 101 | + { | |
| 102 | + return loc.LocationName ?? loc.LocationCode; | |
| 103 | + } | |
| 104 | + return "Specified"; | |
| 105 | + } | |
| 106 | + | |
| 107 | + var items = pageEntities.Select(x => | |
| 108 | + { | |
| 109 | + var lastEdited = x.LastModificationTime ?? x.CreationTime; | |
| 110 | + var contentsCount = elementCountMap.TryGetValue(x.Id, out var c) ? c : 0; | |
| 111 | + var locationText = x.AppliedLocationType == "ALL" ? "All Locations" : GetFirstLocationName(x.Id); | |
| 112 | + var sizeText = $"{x.Width}x{x.Height}{x.Unit}"; | |
| 113 | + | |
| 114 | + return new LabelTemplateGetListOutputDto | |
| 115 | + { | |
| 116 | + Id = x.TemplateCode, // front-end uses templateCode as identifier | |
| 117 | + TemplateCode = x.TemplateCode, | |
| 118 | + TemplateName = x.TemplateName, | |
| 119 | + LabelType = x.LabelType, | |
| 120 | + LocationText = locationText, | |
| 121 | + ContentsCount = contentsCount, | |
| 122 | + SizeText = sizeText, | |
| 123 | + VersionNo = x.VersionNo, | |
| 124 | + LastEdited = lastEdited | |
| 125 | + }; | |
| 126 | + }).ToList(); | |
| 127 | + | |
| 128 | + return BuildPagedResult(input.SkipCount, input.MaxResultCount, total, items); | |
| 129 | + } | |
| 130 | + | |
| 131 | + public async Task<LabelTemplateGetOutputDto> GetAsync(string id) | |
| 132 | + { | |
| 133 | + var template = await _dbContext.SqlSugarClient.Queryable<FlLabelTemplateDbEntity>() | |
| 134 | + .FirstAsync(x => !x.IsDeleted && x.TemplateCode == id); | |
| 135 | + if (template is null) | |
| 136 | + { | |
| 137 | + throw new UserFriendlyException("模板不存在"); | |
| 138 | + } | |
| 139 | + | |
| 140 | + var elements = await _dbContext.SqlSugarClient.Queryable<FlLabelTemplateElementDbEntity>() | |
| 141 | + .Where(x => x.TemplateId == template.Id) | |
| 142 | + .OrderBy(x => x.OrderNum) | |
| 143 | + .ToListAsync(); | |
| 144 | + | |
| 145 | + List<LabelTemplateElementDto> MapElements() | |
| 146 | + { | |
| 147 | + return elements.Select(e => | |
| 148 | + { | |
| 149 | + object? cfg = null; | |
| 150 | + if (!string.IsNullOrWhiteSpace(e.ConfigJson)) | |
| 151 | + { | |
| 152 | + cfg = JsonSerializer.Deserialize<object>(e.ConfigJson); | |
| 153 | + } | |
| 154 | + | |
| 155 | + return new LabelTemplateElementDto | |
| 156 | + { | |
| 157 | + Id = e.ElementKey, | |
| 158 | + ElementType = e.ElementType, | |
| 159 | + PosX = e.PosX, | |
| 160 | + PosY = e.PosY, | |
| 161 | + Width = e.Width, | |
| 162 | + Height = e.Height, | |
| 163 | + Rotation = e.Rotation, | |
| 164 | + BorderType = e.BorderType, | |
| 165 | + ZIndex = e.ZIndex, | |
| 166 | + OrderNum = e.OrderNum, | |
| 167 | + ValueSourceType = e.ValueSourceType, | |
| 168 | + BindingExpr = e.BindingExpr, | |
| 169 | + AutoQueryKey = e.AutoQueryKey, | |
| 170 | + InputKey = e.InputKey, | |
| 171 | + IsRequiredInput = e.IsRequiredInput, | |
| 172 | + ConfigJson = cfg | |
| 173 | + }; | |
| 174 | + }).ToList(); | |
| 175 | + } | |
| 176 | + | |
| 177 | + var appliedLocationIds = await _dbContext.SqlSugarClient.Queryable<FlLabelTemplateLocationDbEntity>() | |
| 178 | + .Where(x => x.TemplateId == template.Id) | |
| 179 | + .Select(x => x.LocationId) | |
| 180 | + .ToListAsync(); | |
| 181 | + | |
| 182 | + return new LabelTemplateGetOutputDto | |
| 183 | + { | |
| 184 | + Id = template.TemplateCode, | |
| 185 | + TemplateCode = template.TemplateCode, | |
| 186 | + TemplateName = template.TemplateName, | |
| 187 | + LabelType = template.LabelType, | |
| 188 | + Unit = template.Unit, | |
| 189 | + Width = template.Width, | |
| 190 | + Height = template.Height, | |
| 191 | + AppliedLocationType = template.AppliedLocationType, | |
| 192 | + ShowRuler = template.ShowRuler, | |
| 193 | + ShowGrid = template.ShowGrid, | |
| 194 | + VersionNo = template.VersionNo, | |
| 195 | + State = template.State, | |
| 196 | + Elements = MapElements(), | |
| 197 | + AppliedLocationIds = appliedLocationIds | |
| 198 | + }; | |
| 199 | + } | |
| 200 | + | |
| 201 | + [UnitOfWork] | |
| 202 | + public async Task<LabelTemplateGetOutputDto> CreateAsync(LabelTemplateCreateInputVo input) | |
| 203 | + { | |
| 204 | + var code = input.TemplateCode?.Trim(); | |
| 205 | + var name = input.TemplateName?.Trim(); | |
| 206 | + if (string.IsNullOrWhiteSpace(code)) | |
| 207 | + { | |
| 208 | + throw new UserFriendlyException("模板编码不能为空"); | |
| 209 | + } | |
| 210 | + if (string.IsNullOrWhiteSpace(name)) | |
| 211 | + { | |
| 212 | + throw new UserFriendlyException("模板名称不能为空"); | |
| 213 | + } | |
| 214 | + | |
| 215 | + var duplicated = await _dbContext.SqlSugarClient.Queryable<FlLabelTemplateDbEntity>() | |
| 216 | + .AnyAsync(x => !x.IsDeleted && x.TemplateCode == code); | |
| 217 | + if (duplicated) | |
| 218 | + { | |
| 219 | + throw new UserFriendlyException("模板编码已存在"); | |
| 220 | + } | |
| 221 | + | |
| 222 | + var now = DateTime.Now; | |
| 223 | + var templateId = _guidGenerator.Create().ToString(); | |
| 224 | + var entity = new FlLabelTemplateDbEntity | |
| 225 | + { | |
| 226 | + Id = templateId, | |
| 227 | + IsDeleted = false, | |
| 228 | + CreationTime = now, | |
| 229 | + CreatorId = CurrentUser?.Id?.ToString(), | |
| 230 | + LastModifierId = CurrentUser?.Id?.ToString(), | |
| 231 | + LastModificationTime = now, | |
| 232 | + ConcurrencyStamp = string.Empty, | |
| 233 | + TemplateCode = code, | |
| 234 | + TemplateName = name, | |
| 235 | + LabelType = input.LabelType, | |
| 236 | + Unit = string.IsNullOrWhiteSpace(input.Unit) ? "inch" : input.Unit.Trim(), | |
| 237 | + Width = input.Width, | |
| 238 | + Height = input.Height, | |
| 239 | + AppliedLocationType = string.IsNullOrWhiteSpace(input.AppliedLocationType) ? "ALL" : input.AppliedLocationType.Trim(), | |
| 240 | + ShowRuler = input.ShowRuler, | |
| 241 | + ShowGrid = input.ShowGrid, | |
| 242 | + VersionNo = 1, | |
| 243 | + State = input.State | |
| 244 | + }; | |
| 245 | + | |
| 246 | + await _dbContext.SqlSugarClient.Insertable(entity).ExecuteCommandAsync(); | |
| 247 | + | |
| 248 | + await RebuildTemplateElementsAndLocationsAsync(entity.Id, input.Elements, entity.AppliedLocationType, input.AppliedLocationIds); | |
| 249 | + | |
| 250 | + return await GetAsync(code); | |
| 251 | + } | |
| 252 | + | |
| 253 | + [UnitOfWork] | |
| 254 | + public async Task<LabelTemplateGetOutputDto> UpdateAsync(string id, LabelTemplateUpdateInputVo input) | |
| 255 | + { | |
| 256 | + var template = await _dbContext.SqlSugarClient.Queryable<FlLabelTemplateDbEntity>() | |
| 257 | + .FirstAsync(x => !x.IsDeleted && x.TemplateCode == id); | |
| 258 | + if (template is null) | |
| 259 | + { | |
| 260 | + throw new UserFriendlyException("模板不存在"); | |
| 261 | + } | |
| 262 | + | |
| 263 | + var code = input.TemplateCode?.Trim(); | |
| 264 | + var name = input.TemplateName?.Trim(); | |
| 265 | + if (!string.IsNullOrWhiteSpace(code) && !string.Equals(code, template.TemplateCode, StringComparison.OrdinalIgnoreCase)) | |
| 266 | + { | |
| 267 | + var duplicated = await _dbContext.SqlSugarClient.Queryable<FlLabelTemplateDbEntity>() | |
| 268 | + .AnyAsync(x => !x.IsDeleted && x.TemplateCode == code); | |
| 269 | + if (duplicated) | |
| 270 | + { | |
| 271 | + throw new UserFriendlyException("模板编码已存在"); | |
| 272 | + } | |
| 273 | + } | |
| 274 | + | |
| 275 | + template.TemplateName = name ?? template.TemplateName; | |
| 276 | + template.LabelType = input.LabelType; | |
| 277 | + template.Unit = string.IsNullOrWhiteSpace(input.Unit) ? template.Unit : input.Unit.Trim(); | |
| 278 | + template.Width = input.Width; | |
| 279 | + template.Height = input.Height; | |
| 280 | + template.AppliedLocationType = string.IsNullOrWhiteSpace(input.AppliedLocationType) ? template.AppliedLocationType : input.AppliedLocationType.Trim(); | |
| 281 | + template.ShowRuler = input.ShowRuler; | |
| 282 | + template.ShowGrid = input.ShowGrid; | |
| 283 | + template.State = input.State; | |
| 284 | + template.VersionNo = template.VersionNo + 1; | |
| 285 | + template.LastModifierId = CurrentUser?.Id?.ToString(); | |
| 286 | + template.LastModificationTime = DateTime.Now; | |
| 287 | + if (!string.IsNullOrWhiteSpace(code)) | |
| 288 | + { | |
| 289 | + template.TemplateCode = code; | |
| 290 | + } | |
| 291 | + | |
| 292 | + await _dbContext.SqlSugarClient.Updateable(template).ExecuteCommandAsync(); | |
| 293 | + | |
| 294 | + await RebuildTemplateElementsAndLocationsAsync(template.Id, input.Elements, template.AppliedLocationType, input.AppliedLocationIds); | |
| 295 | + | |
| 296 | + return await GetAsync(template.TemplateCode); | |
| 297 | + } | |
| 298 | + | |
| 299 | + [UnitOfWork] | |
| 300 | + public async Task DeleteAsync(string id) | |
| 301 | + { | |
| 302 | + var template = await _dbContext.SqlSugarClient.Queryable<FlLabelTemplateDbEntity>() | |
| 303 | + .FirstAsync(x => !x.IsDeleted && x.TemplateCode == id); | |
| 304 | + if (template is null) | |
| 305 | + { | |
| 306 | + return; | |
| 307 | + } | |
| 308 | + | |
| 309 | + var used = await _dbContext.SqlSugarClient.Queryable<FlLabelDbEntity>() | |
| 310 | + .AnyAsync(x => !x.IsDeleted && x.TemplateId == template.Id); | |
| 311 | + | |
| 312 | + if (used) | |
| 313 | + { | |
| 314 | + throw new UserFriendlyException("该模板已被标签引用,无法删除"); | |
| 315 | + } | |
| 316 | + | |
| 317 | + template.IsDeleted = true; | |
| 318 | + template.LastModifierId = CurrentUser?.Id?.ToString(); | |
| 319 | + template.LastModificationTime = DateTime.Now; | |
| 320 | + await _dbContext.SqlSugarClient.Updateable(template).ExecuteCommandAsync(); | |
| 321 | + | |
| 322 | + // 删除子表数据(子表无 IsDeleted 字段) | |
| 323 | + await _dbContext.SqlSugarClient.Deleteable<FlLabelTemplateElementDbEntity>() | |
| 324 | + .Where(x => x.TemplateId == template.Id) | |
| 325 | + .ExecuteCommandAsync(); | |
| 326 | + await _dbContext.SqlSugarClient.Deleteable<FlLabelTemplateLocationDbEntity>() | |
| 327 | + .Where(x => x.TemplateId == template.Id) | |
| 328 | + .ExecuteCommandAsync(); | |
| 329 | + } | |
| 330 | + | |
| 331 | + private async Task RebuildTemplateElementsAndLocationsAsync( | |
| 332 | + string templateDbId, | |
| 333 | + List<LabelTemplateElementDto> elements, | |
| 334 | + string appliedLocationType, | |
| 335 | + List<string> appliedLocationIds) | |
| 336 | + { | |
| 337 | + // elements 重建 | |
| 338 | + await _dbContext.SqlSugarClient.Deleteable<FlLabelTemplateElementDbEntity>() | |
| 339 | + .Where(x => x.TemplateId == templateDbId) | |
| 340 | + .ExecuteCommandAsync(); | |
| 341 | + | |
| 342 | + if (elements is not null && elements.Count > 0) | |
| 343 | + { | |
| 344 | + var now = DateTime.Now; | |
| 345 | + var rows = elements.Select(e => | |
| 346 | + { | |
| 347 | + object? cfg = e.ConfigJson; | |
| 348 | + var configJson = cfg == null ? null : JsonSerializer.Serialize(cfg); | |
| 349 | + return new FlLabelTemplateElementDbEntity | |
| 350 | + { | |
| 351 | + Id = _guidGenerator.Create().ToString(), | |
| 352 | + TemplateId = templateDbId, | |
| 353 | + ElementKey = e.Id, | |
| 354 | + ElementType = e.ElementType, | |
| 355 | + PosX = e.PosX, | |
| 356 | + PosY = e.PosY, | |
| 357 | + Width = e.Width, | |
| 358 | + Height = e.Height, | |
| 359 | + Rotation = string.IsNullOrWhiteSpace(e.Rotation) ? "horizontal" : e.Rotation, | |
| 360 | + BorderType = string.IsNullOrWhiteSpace(e.BorderType) ? "none" : e.BorderType, | |
| 361 | + ZIndex = e.ZIndex, | |
| 362 | + OrderNum = e.OrderNum, | |
| 363 | + ValueSourceType = string.IsNullOrWhiteSpace(e.ValueSourceType) ? "FIXED" : e.ValueSourceType, | |
| 364 | + BindingExpr = e.BindingExpr, | |
| 365 | + AutoQueryKey = e.AutoQueryKey, | |
| 366 | + InputKey = e.InputKey, | |
| 367 | + IsRequiredInput = e.IsRequiredInput, | |
| 368 | + ConfigJson = configJson | |
| 369 | + }; | |
| 370 | + }).ToList(); | |
| 371 | + | |
| 372 | + await _dbContext.SqlSugarClient.Insertable(rows).ExecuteCommandAsync(); | |
| 373 | + } | |
| 374 | + | |
| 375 | + // applied locations 重建 | |
| 376 | + await _dbContext.SqlSugarClient.Deleteable<FlLabelTemplateLocationDbEntity>() | |
| 377 | + .Where(x => x.TemplateId == templateDbId) | |
| 378 | + .ExecuteCommandAsync(); | |
| 379 | + | |
| 380 | + if (string.Equals(appliedLocationType, "SPECIFIED", StringComparison.OrdinalIgnoreCase)) | |
| 381 | + { | |
| 382 | + var ids = appliedLocationIds?.Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim()).Distinct().ToList() ?? new(); | |
| 383 | + if (ids.Count == 0) | |
| 384 | + { | |
| 385 | + throw new UserFriendlyException("指定门店模板必须至少选择一个门店"); | |
| 386 | + } | |
| 387 | + | |
| 388 | + var locRows = ids.Select(locId => new FlLabelTemplateLocationDbEntity | |
| 389 | + { | |
| 390 | + Id = _guidGenerator.Create().ToString(), | |
| 391 | + TemplateId = templateDbId, | |
| 392 | + LocationId = locId | |
| 393 | + }).ToList(); | |
| 394 | + | |
| 395 | + await _dbContext.SqlSugarClient.Insertable(locRows).ExecuteCommandAsync(); | |
| 396 | + } | |
| 397 | + } | |
| 398 | + | |
| 399 | + private static PagedResultWithPageDto<T> BuildPagedResult<T>(int skipCount, int maxResultCount, int total, List<T> items) | |
| 400 | + { | |
| 401 | + var pageSize = maxResultCount <= 0 ? items.Count : maxResultCount; | |
| 402 | + var pageIndex = pageSize <= 0 ? 1 : (skipCount / pageSize) + 1; | |
| 403 | + var totalPages = pageSize <= 0 ? 0 : (int)Math.Ceiling(total / (double)pageSize); | |
| 404 | + return new PagedResultWithPageDto<T> | |
| 405 | + { | |
| 406 | + PageIndex = pageIndex, | |
| 407 | + PageSize = pageSize, | |
| 408 | + TotalCount = total, | |
| 409 | + TotalPages = totalPages, | |
| 410 | + Items = items | |
| 411 | + }; | |
| 412 | + } | |
| 413 | + | |
| 414 | + private static PagedResultWithPageDto<T> BuildPagedResult<T>(int skipCount, int maxResultCount, RefAsync<int> total, List<T> items) | |
| 415 | + { | |
| 416 | + var pageSize = maxResultCount <= 0 ? items.Count : maxResultCount; | |
| 417 | + var pageIndex = pageSize <= 0 ? 1 : (skipCount / pageSize) + 1; | |
| 418 | + var totalPages = pageSize <= 0 ? 0 : (int)Math.Ceiling(total.Value / (double)pageSize); | |
| 419 | + return new PagedResultWithPageDto<T> | |
| 420 | + { | |
| 421 | + PageIndex = pageIndex, | |
| 422 | + PageSize = pageSize, | |
| 423 | + TotalCount = total.Value, | |
| 424 | + TotalPages = totalPages, | |
| 425 | + Items = items | |
| 426 | + }; | |
| 427 | + } | |
| 428 | +} | |
| 429 | + | ... | ... |
美国版/Food Labeling Management Code/Yi.Abp.Net8/module/food-labeling-us/FoodLabeling.Application/Services/LabelTypeAppService.cs
0 → 100644
| 1 | +using FoodLabeling.Application.Contracts.Dtos.Common; | |
| 2 | +using FoodLabeling.Application.Contracts.Dtos.LabelType; | |
| 3 | +using FoodLabeling.Application.Contracts.IServices; | |
| 4 | +using FoodLabeling.Application.Services.DbModels; | |
| 5 | +using SqlSugar; | |
| 6 | +using Volo.Abp; | |
| 7 | +using Volo.Abp.Application.Services; | |
| 8 | +using Volo.Abp.Guids; | |
| 9 | +using Yi.Framework.SqlSugarCore.Abstractions; | |
| 10 | + | |
| 11 | +namespace FoodLabeling.Application.Services; | |
| 12 | + | |
| 13 | +public class LabelTypeAppService : ApplicationService, ILabelTypeAppService | |
| 14 | +{ | |
| 15 | + private readonly ISqlSugarDbContext _dbContext; | |
| 16 | + private readonly IGuidGenerator _guidGenerator; | |
| 17 | + | |
| 18 | + public LabelTypeAppService(ISqlSugarDbContext dbContext, IGuidGenerator guidGenerator) | |
| 19 | + { | |
| 20 | + _dbContext = dbContext; | |
| 21 | + _guidGenerator = guidGenerator; | |
| 22 | + } | |
| 23 | + | |
| 24 | + public async Task<PagedResultWithPageDto<LabelTypeGetListOutputDto>> GetListAsync(LabelTypeGetListInputVo input) | |
| 25 | + { | |
| 26 | + RefAsync<int> total = 0; | |
| 27 | + var keyword = input.Keyword?.Trim(); | |
| 28 | + | |
| 29 | + var query = _dbContext.SqlSugarClient.Queryable<FlLabelTypeDbEntity>() | |
| 30 | + .Where(x => !x.IsDeleted) | |
| 31 | + .WhereIF(!string.IsNullOrWhiteSpace(keyword), x => x.TypeCode.Contains(keyword!) || x.TypeName.Contains(keyword!)) | |
| 32 | + .WhereIF(input.State != null, x => x.State == input.State); | |
| 33 | + | |
| 34 | + if (!string.IsNullOrWhiteSpace(input.Sorting)) | |
| 35 | + { | |
| 36 | + query = query.OrderBy(input.Sorting); | |
| 37 | + } | |
| 38 | + else | |
| 39 | + { | |
| 40 | + query = query.OrderByDescending(x => x.OrderNum).OrderByDescending(x => x.CreationTime); | |
| 41 | + } | |
| 42 | + | |
| 43 | + var entities = await query.ToPageListAsync(input.SkipCount, input.MaxResultCount, total); | |
| 44 | + var ids = entities.Select(x => x.Id).ToList(); | |
| 45 | + | |
| 46 | + var countRows = await _dbContext.SqlSugarClient.Queryable<FlLabelDbEntity>() | |
| 47 | + .Where(x => !x.IsDeleted) | |
| 48 | + .Where(x => x.LabelTypeId != null && ids.Contains(x.LabelTypeId)) | |
| 49 | + .GroupBy(x => x.LabelTypeId) | |
| 50 | + .Select(x => new { TypeId = x.LabelTypeId, Count = SqlFunc.AggregateCount(x.Id) }) | |
| 51 | + .ToListAsync(); | |
| 52 | + var countMap = countRows.ToDictionary(x => x.TypeId!, x => (long)x.Count); | |
| 53 | + | |
| 54 | + var items = entities.Select(x => new LabelTypeGetListOutputDto | |
| 55 | + { | |
| 56 | + Id = x.Id, | |
| 57 | + TypeCode = x.TypeCode, | |
| 58 | + TypeName = x.TypeName, | |
| 59 | + State = x.State, | |
| 60 | + OrderNum = x.OrderNum, | |
| 61 | + NoOfLabels = countMap.TryGetValue(x.Id, out var count) ? count : 0, | |
| 62 | + LastEdited = x.LastModificationTime ?? x.CreationTime | |
| 63 | + }).ToList(); | |
| 64 | + | |
| 65 | + return BuildPagedResult(input.SkipCount, input.MaxResultCount, total, items); | |
| 66 | + } | |
| 67 | + | |
| 68 | + public async Task<LabelTypeGetOutputDto> GetAsync(string id) | |
| 69 | + { | |
| 70 | + var entity = await _dbContext.SqlSugarClient.Queryable<FlLabelTypeDbEntity>() | |
| 71 | + .FirstAsync(x => x.Id == id && !x.IsDeleted); | |
| 72 | + if (entity is null) | |
| 73 | + { | |
| 74 | + throw new UserFriendlyException("标签类型不存在"); | |
| 75 | + } | |
| 76 | + | |
| 77 | + return MapToGetOutput(entity); | |
| 78 | + } | |
| 79 | + | |
| 80 | + public async Task<LabelTypeGetOutputDto> CreateAsync(LabelTypeCreateInputVo input) | |
| 81 | + { | |
| 82 | + var code = input.TypeCode?.Trim(); | |
| 83 | + var name = input.TypeName?.Trim(); | |
| 84 | + if (string.IsNullOrWhiteSpace(code) || string.IsNullOrWhiteSpace(name)) | |
| 85 | + { | |
| 86 | + throw new UserFriendlyException("类型编码和名称不能为空"); | |
| 87 | + } | |
| 88 | + | |
| 89 | + var duplicated = await _dbContext.SqlSugarClient.Queryable<FlLabelTypeDbEntity>() | |
| 90 | + .AnyAsync(x => !x.IsDeleted && (x.TypeCode == code || x.TypeName == name)); | |
| 91 | + if (duplicated) | |
| 92 | + { | |
| 93 | + throw new UserFriendlyException("类型编码或名称已存在"); | |
| 94 | + } | |
| 95 | + | |
| 96 | + var entity = new FlLabelTypeDbEntity | |
| 97 | + { | |
| 98 | + Id = _guidGenerator.Create().ToString(), | |
| 99 | + TypeCode = code, | |
| 100 | + TypeName = name, | |
| 101 | + State = input.State, | |
| 102 | + OrderNum = input.OrderNum | |
| 103 | + }; | |
| 104 | + | |
| 105 | + await _dbContext.SqlSugarClient.Insertable(entity).ExecuteCommandAsync(); | |
| 106 | + return await GetAsync(entity.Id); | |
| 107 | + } | |
| 108 | + | |
| 109 | + public async Task<LabelTypeGetOutputDto> UpdateAsync(string id, LabelTypeUpdateInputVo input) | |
| 110 | + { | |
| 111 | + var entity = await _dbContext.SqlSugarClient.Queryable<FlLabelTypeDbEntity>() | |
| 112 | + .FirstAsync(x => x.Id == id && !x.IsDeleted); | |
| 113 | + if (entity is null) | |
| 114 | + { | |
| 115 | + throw new UserFriendlyException("标签类型不存在"); | |
| 116 | + } | |
| 117 | + | |
| 118 | + var code = input.TypeCode?.Trim(); | |
| 119 | + var name = input.TypeName?.Trim(); | |
| 120 | + if (string.IsNullOrWhiteSpace(code) || string.IsNullOrWhiteSpace(name)) | |
| 121 | + { | |
| 122 | + throw new UserFriendlyException("类型编码和名称不能为空"); | |
| 123 | + } | |
| 124 | + | |
| 125 | + var duplicated = await _dbContext.SqlSugarClient.Queryable<FlLabelTypeDbEntity>() | |
| 126 | + .AnyAsync(x => !x.IsDeleted && x.Id != id && (x.TypeCode == code || x.TypeName == name)); | |
| 127 | + if (duplicated) | |
| 128 | + { | |
| 129 | + throw new UserFriendlyException("类型编码或名称已存在"); | |
| 130 | + } | |
| 131 | + | |
| 132 | + entity.TypeCode = code; | |
| 133 | + entity.TypeName = name; | |
| 134 | + entity.State = input.State; | |
| 135 | + entity.OrderNum = input.OrderNum; | |
| 136 | + entity.LastModificationTime = DateTime.Now; | |
| 137 | + entity.LastModifierId = CurrentUser?.Id?.ToString(); | |
| 138 | + | |
| 139 | + await _dbContext.SqlSugarClient.Updateable(entity).ExecuteCommandAsync(); | |
| 140 | + return await GetAsync(id); | |
| 141 | + } | |
| 142 | + | |
| 143 | + public async Task DeleteAsync(string id) | |
| 144 | + { | |
| 145 | + var entity = await _dbContext.SqlSugarClient.Queryable<FlLabelTypeDbEntity>() | |
| 146 | + .FirstAsync(x => x.Id == id && !x.IsDeleted); | |
| 147 | + if (entity is null) | |
| 148 | + { | |
| 149 | + return; | |
| 150 | + } | |
| 151 | + | |
| 152 | + var used = await _dbContext.SqlSugarClient.Queryable<FlLabelDbEntity>() | |
| 153 | + .AnyAsync(x => !x.IsDeleted && x.LabelTypeId == id); | |
| 154 | + if (used) | |
| 155 | + { | |
| 156 | + throw new UserFriendlyException("该标签类型已被标签引用,无法删除"); | |
| 157 | + } | |
| 158 | + | |
| 159 | + entity.IsDeleted = true; | |
| 160 | + entity.LastModificationTime = DateTime.Now; | |
| 161 | + entity.LastModifierId = CurrentUser?.Id?.ToString(); | |
| 162 | + await _dbContext.SqlSugarClient.Updateable(entity).ExecuteCommandAsync(); | |
| 163 | + } | |
| 164 | + | |
| 165 | + private static LabelTypeGetOutputDto MapToGetOutput(FlLabelTypeDbEntity x) | |
| 166 | + { | |
| 167 | + return new LabelTypeGetOutputDto | |
| 168 | + { | |
| 169 | + Id = x.Id, | |
| 170 | + TypeCode = x.TypeCode, | |
| 171 | + TypeName = x.TypeName, | |
| 172 | + State = x.State, | |
| 173 | + OrderNum = x.OrderNum | |
| 174 | + }; | |
| 175 | + } | |
| 176 | + | |
| 177 | + private static PagedResultWithPageDto<T> BuildPagedResult<T>(int skipCount, int maxResultCount, int total, List<T> items) | |
| 178 | + { | |
| 179 | + var pageSize = maxResultCount <= 0 ? items.Count : maxResultCount; | |
| 180 | + var pageIndex = pageSize <= 0 ? 1 : (skipCount / pageSize) + 1; | |
| 181 | + var totalPages = pageSize <= 0 ? 0 : (int)Math.Ceiling(total / (double)pageSize); | |
| 182 | + return new PagedResultWithPageDto<T> | |
| 183 | + { | |
| 184 | + PageIndex = pageIndex, | |
| 185 | + PageSize = pageSize, | |
| 186 | + TotalCount = total, | |
| 187 | + TotalPages = totalPages, | |
| 188 | + Items = items | |
| 189 | + }; | |
| 190 | + } | |
| 191 | +} | |
| 192 | + | ... | ... |