Browse Source

添加AttachFile API

luocaiyang 4 năm trước cách đây
mục cha
commit
6b92a6e4ee

+ 105 - 0
wispro.sp.api/Controllers/AttachFilesController.cs

@@ -0,0 +1,105 @@
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Threading.Tasks;
+using wispro.sp.share;
+
+namespace wispro.sp.api.Controllers
+{
+    [Route("api/[controller]/[action]")]
+    [ApiController]
+    public class AttachFilesController : ControllerBase
+    {
+        private readonly IWebHostEnvironment env;
+        private readonly ILogger<AttachFilesController> logger;
+
+        public AttachFilesController(IWebHostEnvironment env,
+            ILogger<AttachFilesController> logger)
+        {
+            this.env = env;
+            this.logger = logger;
+        }
+
+        [HttpPost]
+        public async Task<ActionResult<IList<UploadResult>>> PostFile(
+        [FromForm] IEnumerable<IFormFile> files)
+        {
+            
+            var maxAllowedFiles = 3;
+            long maxFileSize = 1024 * 1024 * 15;
+            var filesProcessed = 0;
+            var resourcePath = new Uri($"{Request.Scheme}://{Request.Host}/");
+            List<UploadResult> uploadResults = new();
+
+            foreach (var file in files)
+            {
+                var uploadResult = new UploadResult();
+                string trustedFileNameForFileStorage;
+                var untrustedFileName = file.FileName;
+                uploadResult.FileName = untrustedFileName;
+                var trustedFileNameForDisplay =
+                    WebUtility.HtmlEncode(untrustedFileName);
+
+                if (filesProcessed < maxAllowedFiles)
+                {
+                    if (file.Length == 0)
+                    {
+                        logger.LogInformation("{FileName} length is 0 (Err: 1)",
+                            trustedFileNameForDisplay);
+                        uploadResult.ErrorCode = 1;
+                    }
+                    else if (file.Length > maxFileSize)
+                    {
+                        logger.LogInformation("{FileName} of {Length} bytes is " +
+                            "larger than the limit of {Limit} bytes (Err: 2)",
+                            trustedFileNameForDisplay, file.Length, maxFileSize);
+                        uploadResult.ErrorCode = 2;
+                    }
+                    else
+                    {
+                        try
+                        {
+                            trustedFileNameForFileStorage = Path.GetRandomFileName();
+                            var path = Path.Combine(env.ContentRootPath,
+                                env.EnvironmentName, "unsafe_uploads",
+                                trustedFileNameForFileStorage);
+
+                            await using FileStream fs = new(path, FileMode.Create);
+                            await file.CopyToAsync(fs);
+
+                            logger.LogInformation("{FileName} saved at {Path}",
+                                trustedFileNameForDisplay, path);
+                            uploadResult.Uploaded = true;
+                            uploadResult.StoredFileName = trustedFileNameForFileStorage;
+                        }
+                        catch (IOException ex)
+                        {
+                            logger.LogError("{FileName} error on upload (Err: 3): {Message}",
+                                trustedFileNameForDisplay, ex.Message);
+                            uploadResult.ErrorCode = 3;
+                        }
+                    }
+
+                    filesProcessed++;
+                }
+                else
+                {
+                    logger.LogInformation("{FileName} not uploaded because the " +
+                        "request exceeded the allowed {Count} of files (Err: 4)",
+                        trustedFileNameForDisplay, maxAllowedFiles);
+                    uploadResult.ErrorCode = 4;
+                }
+
+                uploadResults.Add(uploadResult);
+            }
+
+            return new CreatedResult(resourcePath, uploadResults);
+        }
+    }
+}

+ 46 - 22
wispro.sp.api/Controllers/PerformanceItemController.cs

@@ -25,10 +25,27 @@ namespace wispro.sp.api.Controllers
         public ApiSaveResponse New(PerformanceItem item)
         {
             ApiSaveResponse ret = new ApiSaveResponse();
+            ret.Success = true;
+
             using (Context.Database.BeginTransaction())
             {
                 try
                 {
+                    if(item.CalMonth != null)
+                    {
+                        var calMonth = Context.CalMonths.Where<CalMonth>(c => c.Year  == item.CalMonth.Year && c.Month == item.CalMonth.Month).FirstOrDefault();
+                        if(calMonth == null)
+                        {
+                            Context.CalMonths.Add(item.CalMonth);
+                            Context.SaveChanges();
+                        }
+                        else
+                        {
+                            item.CalMonth = calMonth;
+                        }
+                        item.CalMonthId = item.CalMonth.Id;
+                        item.CalMonth = null;
+                    }
 
                     if (!string.IsNullOrEmpty(item.Customer.Name))
                     {
@@ -45,6 +62,7 @@ namespace wispro.sp.api.Controllers
                         }
 
                         item.CustomerId = item.Customer.Id;
+                        item.Customer = null;
                     }
                     else
                     {
@@ -61,34 +79,40 @@ namespace wispro.sp.api.Controllers
                     }
                     else
                     {
-                        Context.PerformanceItems.Add(item);
-                    }
-
-                    Context.SaveChanges();
+                        var ItemStaffs = item.ItemStaffs;
+                        item.ItemStaffs = null;
 
-                    foreach(ItemStaff itemStaff in item.ItemStaffs)
-                    {
-                        itemStaff.ItemId = item.Id;
+                        Context.PerformanceItems.Add(item);
+                        Context.SaveChanges();
 
-                        if(itemStaff.DoPersonId ==0 && itemStaff.DoPerson != null)
+                        foreach (ItemStaff itemStaff in ItemStaffs)
                         {
-                            var temStaff = Context.Staffs.FirstOrDefault<Staff>(s => s.Name == itemStaff.DoPerson.Name);
+                            itemStaff.ItemId = item.Id;
+                            itemStaff.Item = null;
 
-                            if(temStaff != null)
+                            if (itemStaff.DoPersonId == 0 && itemStaff.DoPerson != null)
                             {
-                                itemStaff.DoPersonId = temStaff.Id;
-                                itemStaff.DoPerson = null;
-                            }
-                            else
-                            {
-                                Context.Staffs.Add(itemStaff.DoPerson);
-                                Context.SaveChanges();
-                                itemStaff.DoPersonId = itemStaff.DoPerson.Id;
+                                var temStaff = Context.Staffs.FirstOrDefault<Staff>(s => s.Name == itemStaff.DoPerson.Name);
+
+                                if (temStaff != null)
+                                {
+                                    itemStaff.DoPersonId = temStaff.Id;
+                                    itemStaff.DoPerson = null;
+                                }
+                                else
+                                {
+                                    Context.Staffs.Add(itemStaff.DoPerson);
+                                    Context.SaveChanges();
+                                    itemStaff.DoPersonId = itemStaff.DoPerson.Id;
+                                    itemStaff.DoPerson = null;
+                                }
                             }
                         }
-                    }
 
-                    Context.ItemStaffs.AddRange(item.ItemStaffs);
+                        Context.ItemStaffs.AddRange(ItemStaffs);
+                        Context.SaveChanges();
+                        
+                    }
 
                     Context.Database.CommitTransaction();
                 }
@@ -110,7 +134,7 @@ namespace wispro.sp.api.Controllers
             var results = Context.PerformanceItems
                 .Where<PerformanceItem>(s => 
                     (s.ItemStaffs.Where<ItemStaff>(iStaff => iStaff.DoPerson.Name == User.Identity.Name).Count() > 0 || s.Reviewer.Name == User.Identity.Name) 
-                    && s.Month == 7 && s.Year == 2021);
+                    && s.CalMonth.Month == 7 && s.CalMonth.Year == 2021);
 
             ret.TotalCount = results.Count();
 
@@ -134,7 +158,7 @@ namespace wispro.sp.api.Controllers
 
             List<PerformanceItem> retList = Context.PerformanceItems
                 .Where<PerformanceItem>(s => (s.ItemStaffs
-                    .Where<ItemStaff>(iStaff => iStaff.DoPerson.Name == queryFilter.PersonName) .Count() > 0 || s.Reviewer.Name == queryFilter.PersonName) && s.Month == queryFilter.Month && s.Year == queryFilter.Year)
+                    .Where<ItemStaff>(iStaff => iStaff.DoPerson.Name == queryFilter.PersonName) .Count() > 0 || s.Reviewer.Name == queryFilter.PersonName) && s.CalMonth.Month == queryFilter.Month && s.CalMonth.Year == queryFilter.Year)
                 .Include(pi => pi.ItemStaffs).ThenInclude(iStaff => iStaff.DoPerson)
                 .Include(pi => pi.Reviewer)
                 .Include(pi => pi.Customer)

BIN
wispro.sp.api/Development/unsafe_uploads/h05esglb.ev1


BIN
wispro.sp.api/Development/unsafe_uploads/vjonbppp.0dv


+ 235 - 7
wispro.sp.api/Migrations/20210910105657_spDB0910.Designer.cs

@@ -10,22 +10,89 @@ using wispro.sp.api;
 namespace wispro.sp.api.Migrations
 {
     [DbContext(typeof(spDbContext))]
-    [Migration("20210910105657_spDB0910")]
-    partial class spDB0910
+    [Migration("20211020061916_CalMonth")]
+    partial class CalMonth
     {
         protected override void BuildTargetModel(ModelBuilder modelBuilder)
         {
 #pragma warning disable 612, 618
             modelBuilder
-                .HasAnnotation("Relational:Collation", "Chinese_PRC_CI_AS")
                 .HasAnnotation("Relational:MaxIdentifierLength", 128)
                 .HasAnnotation("ProductVersion", "5.0.9")
                 .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
 
+            modelBuilder.Entity("wispro.sp.entity.AttachFile", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(200)
+                        .HasColumnType("nvarchar(200)");
+
+                    b.Property<string>("SavePath")
+                        .HasMaxLength(200)
+                        .HasColumnType("nvarchar(200)");
+
+                    b.Property<int>("UploadUserId")
+                        .HasColumnType("int");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UploadUserId");
+
+                    b.ToTable("AttachFile");
+                });
+
+            modelBuilder.Entity("wispro.sp.entity.BasePointRule", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+                    b.Property<double>("Point")
+                        .HasColumnType("float");
+
+                    b.Property<string>("Rule")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("BasePointRules");
+                });
+
+            modelBuilder.Entity("wispro.sp.entity.CalMonth", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+                    b.Property<int>("Month")
+                        .HasColumnType("int")
+                        .HasColumnName("month");
+
+                    b.Property<int>("Status")
+                        .HasColumnType("int")
+                        .HasColumnName("status");
+
+                    b.Property<int>("Year")
+                        .HasColumnType("int")
+                        .HasColumnName("year");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("CalMonth");
+                });
+
             modelBuilder.Entity("wispro.sp.entity.Customer", b =>
                 {
                     b.Property<int>("Id")
-                        .HasColumnType("int");
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
 
                     b.Property<string>("Address")
                         .HasMaxLength(500)
@@ -72,6 +139,67 @@ namespace wispro.sp.api.Migrations
                     b.ToTable("ItemStaff");
                 });
 
+            modelBuilder.Entity("wispro.sp.entity.Message", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<int>("FromId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("MessageInfo")
+                        .HasMaxLength(500)
+                        .HasColumnType("nvarchar(500)");
+
+                    b.Property<int>("Type")
+                        .HasColumnType("int");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("FromId");
+
+                    b.ToTable("Message");
+                });
+
+            modelBuilder.Entity("wispro.sp.entity.MessagePerformanceItem", b =>
+                {
+                    b.Property<int>("ItemId")
+                        .HasColumnType("int");
+
+                    b.Property<Guid>("MessageId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.HasKey("ItemId", "MessageId");
+
+                    b.HasIndex("MessageId");
+
+                    b.ToTable("MessagePerformanceItems");
+                });
+
+            modelBuilder.Entity("wispro.sp.entity.MessageReadRecord", b =>
+                {
+                    b.Property<Guid>("MessageId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<int>("StaffId")
+                        .HasColumnType("int");
+
+                    b.Property<Guid?>("MessageId1")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<bool>("isReaded")
+                        .HasColumnType("bit");
+
+                    b.HasKey("MessageId", "StaffId");
+
+                    b.HasIndex("MessageId1");
+
+                    b.HasIndex("StaffId");
+
+                    b.ToTable("MessageReadRecord");
+                });
+
             modelBuilder.Entity("wispro.sp.entity.PerformanceItem", b =>
                 {
                     b.Property<int>("Id")
@@ -97,10 +225,16 @@ namespace wispro.sp.api.Migrations
                         .HasMaxLength(50)
                         .HasColumnType("nvarchar(50)");
 
+                    b.Property<int>("CalMonthId")
+                        .HasColumnType("int");
+
                     b.Property<string>("CaseCoefficient")
                         .HasMaxLength(10)
                         .HasColumnType("nvarchar(10)");
 
+                    b.Property<string>("CaseMemo")
+                        .HasColumnType("nvarchar(max)");
+
                     b.Property<string>("CaseName")
                         .HasMaxLength(500)
                         .HasColumnType("nvarchar(500)");
@@ -179,14 +313,15 @@ namespace wispro.sp.api.Migrations
                         .HasColumnType("int");
 
                     b.Property<int?>("Status")
-                        .HasColumnType("int")
-                        .HasColumnName("status");
+                        .HasColumnType("int");
 
                     b.Property<int>("Year")
                         .HasColumnType("int");
 
                     b.HasKey("Id");
 
+                    b.HasIndex("CalMonthId");
+
                     b.HasIndex("CustomerId");
 
                     b.HasIndex("PreOastaffId");
@@ -201,7 +336,9 @@ namespace wispro.sp.api.Migrations
             modelBuilder.Entity("wispro.sp.entity.Staff", b =>
                 {
                     b.Property<int>("Id")
-                        .HasColumnType("int");
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
 
                     b.Property<string>("Account")
                         .IsRequired()
@@ -219,6 +356,9 @@ namespace wispro.sp.api.Migrations
                         .HasColumnType("bit")
                         .HasColumnName("isCalPerformsnce");
 
+                    b.Property<string>("Mail")
+                        .HasColumnType("nvarchar(max)");
+
                     b.Property<string>("Memo")
                         .HasColumnType("nvarchar(max)");
 
@@ -533,6 +673,18 @@ namespace wispro.sp.api.Migrations
                         });
                 });
 
+            modelBuilder.Entity("wispro.sp.entity.AttachFile", b =>
+                {
+                    b.HasOne("wispro.sp.entity.Staff", "UploadUser")
+                        .WithMany()
+                        .HasForeignKey("UploadUserId")
+                        .HasConstraintName("FK_AttachFile_UpdateUser")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("UploadUser");
+                });
+
             modelBuilder.Entity("wispro.sp.entity.Customer", b =>
                 {
                     b.HasOne("wispro.sp.entity.Staff", "ResponseMan")
@@ -562,8 +714,70 @@ namespace wispro.sp.api.Migrations
                     b.Navigation("Item");
                 });
 
+            modelBuilder.Entity("wispro.sp.entity.Message", b =>
+                {
+                    b.HasOne("wispro.sp.entity.Staff", "From")
+                        .WithMany()
+                        .HasForeignKey("FromId")
+                        .HasConstraintName("FK_From_Staff")
+                        .IsRequired();
+
+                    b.Navigation("From");
+                });
+
+            modelBuilder.Entity("wispro.sp.entity.MessagePerformanceItem", b =>
+                {
+                    b.HasOne("wispro.sp.entity.PerformanceItem", "Item")
+                        .WithMany()
+                        .HasForeignKey("ItemId")
+                        .HasConstraintName("FK_MessagePerformanceItem_Item")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("wispro.sp.entity.Message", "Message")
+                        .WithMany("RelatedItem")
+                        .HasForeignKey("MessageId")
+                        .HasConstraintName("FK_MessagePerformanceItem_Message")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Item");
+
+                    b.Navigation("Message");
+                });
+
+            modelBuilder.Entity("wispro.sp.entity.MessageReadRecord", b =>
+                {
+                    b.HasOne("wispro.sp.entity.Message", "Message")
+                        .WithMany()
+                        .HasForeignKey("MessageId")
+                        .HasConstraintName("FK_MessageReadRecord_Message")
+                        .IsRequired();
+
+                    b.HasOne("wispro.sp.entity.Message", null)
+                        .WithMany("To")
+                        .HasForeignKey("MessageId1");
+
+                    b.HasOne("wispro.sp.entity.Staff", "Staff")
+                        .WithMany()
+                        .HasForeignKey("StaffId")
+                        .HasConstraintName("FK_MessageReadRecord_Staff")
+                        .IsRequired();
+
+                    b.Navigation("Message");
+
+                    b.Navigation("Staff");
+                });
+
             modelBuilder.Entity("wispro.sp.entity.PerformanceItem", b =>
                 {
+                    b.HasOne("wispro.sp.entity.CalMonth", "CalMonth")
+                        .WithMany("PerformanceItems")
+                        .HasForeignKey("CalMonthId")
+                        .HasConstraintName("FK_PerformanceItem_CalMonth")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
                     b.HasOne("wispro.sp.entity.Customer", "Customer")
                         .WithMany("PerformanceItems")
                         .HasForeignKey("CustomerId")
@@ -583,6 +797,8 @@ namespace wispro.sp.api.Migrations
                         .WithMany("PerformanceItems")
                         .HasForeignKey("StaffId");
 
+                    b.Navigation("CalMonth");
+
                     b.Navigation("Customer");
 
                     b.Navigation("PreOastaff");
@@ -620,11 +836,23 @@ namespace wispro.sp.api.Migrations
                     b.Navigation("DoPerson");
                 });
 
+            modelBuilder.Entity("wispro.sp.entity.CalMonth", b =>
+                {
+                    b.Navigation("PerformanceItems");
+                });
+
             modelBuilder.Entity("wispro.sp.entity.Customer", b =>
                 {
                     b.Navigation("PerformanceItems");
                 });
 
+            modelBuilder.Entity("wispro.sp.entity.Message", b =>
+                {
+                    b.Navigation("RelatedItem");
+
+                    b.Navigation("To");
+                });
+
             modelBuilder.Entity("wispro.sp.entity.PerformanceItem", b =>
                 {
                     b.Navigation("ItemStaffs");

+ 188 - 4
wispro.sp.api/Migrations/20210910105657_spDB0910.cs

@@ -3,11 +3,40 @@ using Microsoft.EntityFrameworkCore.Migrations;
 
 namespace wispro.sp.api.Migrations
 {
-    public partial class spDB0910 : Migration
+    public partial class CalMonth : Migration
     {
         protected override void Up(MigrationBuilder migrationBuilder)
         {
             migrationBuilder.CreateTable(
+                name: "BasePointRules",
+                columns: table => new
+                {
+                    Id = table.Column<int>(type: "int", nullable: false)
+                        .Annotation("SqlServer:Identity", "1, 1"),
+                    Rule = table.Column<string>(type: "nvarchar(max)", nullable: true),
+                    Point = table.Column<double>(type: "float", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_BasePointRules", x => x.Id);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "CalMonth",
+                columns: table => new
+                {
+                    Id = table.Column<int>(type: "int", nullable: false)
+                        .Annotation("SqlServer:Identity", "1, 1"),
+                    year = table.Column<int>(type: "int", nullable: false),
+                    month = table.Column<int>(type: "int", nullable: false),
+                    status = table.Column<int>(type: "int", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_CalMonth", x => x.Id);
+                });
+
+            migrationBuilder.CreateTable(
                 name: "StaffGrade",
                 columns: table => new
                 {
@@ -25,7 +54,8 @@ namespace wispro.sp.api.Migrations
                 name: "Staff",
                 columns: table => new
                 {
-                    Id = table.Column<int>(type: "int", nullable: false),
+                    Id = table.Column<int>(type: "int", nullable: false)
+                        .Annotation("SqlServer:Identity", "1, 1"),
                     Account = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
                     Password = table.Column<string>(type: "nvarchar(max)", nullable: false),
                     Name = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
@@ -35,6 +65,7 @@ namespace wispro.sp.api.Migrations
                     Department = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
                     WorkPlace = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
                     EntyDate = table.Column<DateTime>(type: "date", nullable: true),
+                    Mail = table.Column<string>(type: "nvarchar(max)", nullable: true),
                     Memo = table.Column<string>(type: "nvarchar(max)", nullable: true)
                 },
                 constraints: table =>
@@ -74,10 +105,31 @@ namespace wispro.sp.api.Migrations
                 });
 
             migrationBuilder.CreateTable(
+                name: "AttachFile",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+                    Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
+                    SavePath = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
+                    UploadUserId = table.Column<int>(type: "int", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_AttachFile", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_AttachFile_UpdateUser",
+                        column: x => x.UploadUserId,
+                        principalTable: "Staff",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateTable(
                 name: "Customer",
                 columns: table => new
                 {
-                    Id = table.Column<int>(type: "int", nullable: false),
+                    Id = table.Column<int>(type: "int", nullable: false)
+                        .Annotation("SqlServer:Identity", "1, 1"),
                     Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
                     ContactMan = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
                     Address = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
@@ -96,6 +148,26 @@ namespace wispro.sp.api.Migrations
                 });
 
             migrationBuilder.CreateTable(
+                name: "Message",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+                    MessageInfo = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
+                    Type = table.Column<int>(type: "int", nullable: false),
+                    FromId = table.Column<int>(type: "int", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Message", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_From_Staff",
+                        column: x => x.FromId,
+                        principalTable: "Staff",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                });
+
+            migrationBuilder.CreateTable(
                 name: "PerformanceItem",
                 columns: table => new
                 {
@@ -129,13 +201,21 @@ namespace wispro.sp.api.Migrations
                     FirstDraftDate = table.Column<DateTime>(type: "date", nullable: true),
                     OverDueMemo = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
                     BasePoint = table.Column<decimal>(type: "numeric(18,2)", nullable: true),
-                    status = table.Column<int>(type: "int", nullable: true),
+                    Status = table.Column<int>(type: "int", nullable: true),
+                    CaseMemo = table.Column<string>(type: "nvarchar(max)", nullable: true),
+                    CalMonthId = table.Column<int>(type: "int", nullable: false),
                     StaffId = table.Column<int>(type: "int", nullable: true)
                 },
                 constraints: table =>
                 {
                     table.PrimaryKey("PK_PerformanceItem", x => x.Id);
                     table.ForeignKey(
+                        name: "FK_PerformanceItem_CalMonth",
+                        column: x => x.CalMonthId,
+                        principalTable: "CalMonth",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
                         name: "FK_PerformanceItem_Customer",
                         column: x => x.CustomerId,
                         principalTable: "Customer",
@@ -162,6 +242,38 @@ namespace wispro.sp.api.Migrations
                 });
 
             migrationBuilder.CreateTable(
+                name: "MessageReadRecord",
+                columns: table => new
+                {
+                    MessageId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+                    StaffId = table.Column<int>(type: "int", nullable: false),
+                    isReaded = table.Column<bool>(type: "bit", nullable: false),
+                    MessageId1 = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_MessageReadRecord", x => new { x.MessageId, x.StaffId });
+                    table.ForeignKey(
+                        name: "FK_MessageReadRecord_Message",
+                        column: x => x.MessageId,
+                        principalTable: "Message",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                    table.ForeignKey(
+                        name: "FK_MessageReadRecord_Message_MessageId1",
+                        column: x => x.MessageId1,
+                        principalTable: "Message",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                    table.ForeignKey(
+                        name: "FK_MessageReadRecord_Staff",
+                        column: x => x.StaffId,
+                        principalTable: "Staff",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                });
+
+            migrationBuilder.CreateTable(
                 name: "ItemStaff",
                 columns: table => new
                 {
@@ -186,6 +298,30 @@ namespace wispro.sp.api.Migrations
                         onDelete: ReferentialAction.Restrict);
                 });
 
+            migrationBuilder.CreateTable(
+                name: "MessagePerformanceItems",
+                columns: table => new
+                {
+                    MessageId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
+                    ItemId = table.Column<int>(type: "int", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_MessagePerformanceItems", x => new { x.ItemId, x.MessageId });
+                    table.ForeignKey(
+                        name: "FK_MessagePerformanceItem_Item",
+                        column: x => x.ItemId,
+                        principalTable: "PerformanceItem",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_MessagePerformanceItem_Message",
+                        column: x => x.MessageId,
+                        principalTable: "Message",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
             migrationBuilder.InsertData(
                 table: "StaffGrade",
                 columns: new[] { "Id", "Coefficient", "Grade" },
@@ -241,6 +377,11 @@ namespace wispro.sp.api.Migrations
                 });
 
             migrationBuilder.CreateIndex(
+                name: "IX_AttachFile_UploadUserId",
+                table: "AttachFile",
+                column: "UploadUserId");
+
+            migrationBuilder.CreateIndex(
                 name: "IX_Customer_ResponseManId",
                 table: "Customer",
                 column: "ResponseManId");
@@ -251,6 +392,31 @@ namespace wispro.sp.api.Migrations
                 column: "DoPersonId");
 
             migrationBuilder.CreateIndex(
+                name: "IX_Message_FromId",
+                table: "Message",
+                column: "FromId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_MessagePerformanceItems_MessageId",
+                table: "MessagePerformanceItems",
+                column: "MessageId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_MessageReadRecord_MessageId1",
+                table: "MessageReadRecord",
+                column: "MessageId1");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_MessageReadRecord_StaffId",
+                table: "MessageReadRecord",
+                column: "StaffId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_PerformanceItem_CalMonthId",
+                table: "PerformanceItem",
+                column: "CalMonthId");
+
+            migrationBuilder.CreateIndex(
                 name: "IX_PerformanceItem_CustomerId",
                 table: "PerformanceItem",
                 column: "CustomerId");
@@ -284,15 +450,33 @@ namespace wispro.sp.api.Migrations
         protected override void Down(MigrationBuilder migrationBuilder)
         {
             migrationBuilder.DropTable(
+                name: "AttachFile");
+
+            migrationBuilder.DropTable(
+                name: "BasePointRules");
+
+            migrationBuilder.DropTable(
                 name: "ItemStaff");
 
             migrationBuilder.DropTable(
+                name: "MessagePerformanceItems");
+
+            migrationBuilder.DropTable(
+                name: "MessageReadRecord");
+
+            migrationBuilder.DropTable(
                 name: "VerifyCoefficient");
 
             migrationBuilder.DropTable(
                 name: "PerformanceItem");
 
             migrationBuilder.DropTable(
+                name: "Message");
+
+            migrationBuilder.DropTable(
+                name: "CalMonth");
+
+            migrationBuilder.DropTable(
                 name: "Customer");
 
             migrationBuilder.DropTable(

+ 233 - 5
wispro.sp.api/Migrations/spDbContextModelSnapshot.cs

@@ -15,15 +15,82 @@ namespace wispro.sp.api.Migrations
         {
 #pragma warning disable 612, 618
             modelBuilder
-                .HasAnnotation("Relational:Collation", "Chinese_PRC_CI_AS")
                 .HasAnnotation("Relational:MaxIdentifierLength", 128)
                 .HasAnnotation("ProductVersion", "5.0.9")
                 .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
 
+            modelBuilder.Entity("wispro.sp.entity.AttachFile", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(200)
+                        .HasColumnType("nvarchar(200)");
+
+                    b.Property<string>("SavePath")
+                        .HasMaxLength(200)
+                        .HasColumnType("nvarchar(200)");
+
+                    b.Property<int>("UploadUserId")
+                        .HasColumnType("int");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UploadUserId");
+
+                    b.ToTable("AttachFile");
+                });
+
+            modelBuilder.Entity("wispro.sp.entity.BasePointRule", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+                    b.Property<double>("Point")
+                        .HasColumnType("float");
+
+                    b.Property<string>("Rule")
+                        .HasColumnType("nvarchar(max)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("BasePointRules");
+                });
+
+            modelBuilder.Entity("wispro.sp.entity.CalMonth", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+                    b.Property<int>("Month")
+                        .HasColumnType("int")
+                        .HasColumnName("month");
+
+                    b.Property<int>("Status")
+                        .HasColumnType("int")
+                        .HasColumnName("status");
+
+                    b.Property<int>("Year")
+                        .HasColumnType("int")
+                        .HasColumnName("year");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("CalMonth");
+                });
+
             modelBuilder.Entity("wispro.sp.entity.Customer", b =>
                 {
                     b.Property<int>("Id")
-                        .HasColumnType("int");
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
 
                     b.Property<string>("Address")
                         .HasMaxLength(500)
@@ -70,6 +137,67 @@ namespace wispro.sp.api.Migrations
                     b.ToTable("ItemStaff");
                 });
 
+            modelBuilder.Entity("wispro.sp.entity.Message", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<int>("FromId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("MessageInfo")
+                        .HasMaxLength(500)
+                        .HasColumnType("nvarchar(500)");
+
+                    b.Property<int>("Type")
+                        .HasColumnType("int");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("FromId");
+
+                    b.ToTable("Message");
+                });
+
+            modelBuilder.Entity("wispro.sp.entity.MessagePerformanceItem", b =>
+                {
+                    b.Property<int>("ItemId")
+                        .HasColumnType("int");
+
+                    b.Property<Guid>("MessageId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.HasKey("ItemId", "MessageId");
+
+                    b.HasIndex("MessageId");
+
+                    b.ToTable("MessagePerformanceItems");
+                });
+
+            modelBuilder.Entity("wispro.sp.entity.MessageReadRecord", b =>
+                {
+                    b.Property<Guid>("MessageId")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<int>("StaffId")
+                        .HasColumnType("int");
+
+                    b.Property<Guid?>("MessageId1")
+                        .HasColumnType("uniqueidentifier");
+
+                    b.Property<bool>("isReaded")
+                        .HasColumnType("bit");
+
+                    b.HasKey("MessageId", "StaffId");
+
+                    b.HasIndex("MessageId1");
+
+                    b.HasIndex("StaffId");
+
+                    b.ToTable("MessageReadRecord");
+                });
+
             modelBuilder.Entity("wispro.sp.entity.PerformanceItem", b =>
                 {
                     b.Property<int>("Id")
@@ -95,10 +223,16 @@ namespace wispro.sp.api.Migrations
                         .HasMaxLength(50)
                         .HasColumnType("nvarchar(50)");
 
+                    b.Property<int>("CalMonthId")
+                        .HasColumnType("int");
+
                     b.Property<string>("CaseCoefficient")
                         .HasMaxLength(10)
                         .HasColumnType("nvarchar(10)");
 
+                    b.Property<string>("CaseMemo")
+                        .HasColumnType("nvarchar(max)");
+
                     b.Property<string>("CaseName")
                         .HasMaxLength(500)
                         .HasColumnType("nvarchar(500)");
@@ -177,14 +311,15 @@ namespace wispro.sp.api.Migrations
                         .HasColumnType("int");
 
                     b.Property<int?>("Status")
-                        .HasColumnType("int")
-                        .HasColumnName("status");
+                        .HasColumnType("int");
 
                     b.Property<int>("Year")
                         .HasColumnType("int");
 
                     b.HasKey("Id");
 
+                    b.HasIndex("CalMonthId");
+
                     b.HasIndex("CustomerId");
 
                     b.HasIndex("PreOastaffId");
@@ -199,7 +334,9 @@ namespace wispro.sp.api.Migrations
             modelBuilder.Entity("wispro.sp.entity.Staff", b =>
                 {
                     b.Property<int>("Id")
-                        .HasColumnType("int");
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int")
+                        .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
 
                     b.Property<string>("Account")
                         .IsRequired()
@@ -217,6 +354,9 @@ namespace wispro.sp.api.Migrations
                         .HasColumnType("bit")
                         .HasColumnName("isCalPerformsnce");
 
+                    b.Property<string>("Mail")
+                        .HasColumnType("nvarchar(max)");
+
                     b.Property<string>("Memo")
                         .HasColumnType("nvarchar(max)");
 
@@ -531,6 +671,18 @@ namespace wispro.sp.api.Migrations
                         });
                 });
 
+            modelBuilder.Entity("wispro.sp.entity.AttachFile", b =>
+                {
+                    b.HasOne("wispro.sp.entity.Staff", "UploadUser")
+                        .WithMany()
+                        .HasForeignKey("UploadUserId")
+                        .HasConstraintName("FK_AttachFile_UpdateUser")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("UploadUser");
+                });
+
             modelBuilder.Entity("wispro.sp.entity.Customer", b =>
                 {
                     b.HasOne("wispro.sp.entity.Staff", "ResponseMan")
@@ -560,8 +712,70 @@ namespace wispro.sp.api.Migrations
                     b.Navigation("Item");
                 });
 
+            modelBuilder.Entity("wispro.sp.entity.Message", b =>
+                {
+                    b.HasOne("wispro.sp.entity.Staff", "From")
+                        .WithMany()
+                        .HasForeignKey("FromId")
+                        .HasConstraintName("FK_From_Staff")
+                        .IsRequired();
+
+                    b.Navigation("From");
+                });
+
+            modelBuilder.Entity("wispro.sp.entity.MessagePerformanceItem", b =>
+                {
+                    b.HasOne("wispro.sp.entity.PerformanceItem", "Item")
+                        .WithMany()
+                        .HasForeignKey("ItemId")
+                        .HasConstraintName("FK_MessagePerformanceItem_Item")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("wispro.sp.entity.Message", "Message")
+                        .WithMany("RelatedItem")
+                        .HasForeignKey("MessageId")
+                        .HasConstraintName("FK_MessagePerformanceItem_Message")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Item");
+
+                    b.Navigation("Message");
+                });
+
+            modelBuilder.Entity("wispro.sp.entity.MessageReadRecord", b =>
+                {
+                    b.HasOne("wispro.sp.entity.Message", "Message")
+                        .WithMany()
+                        .HasForeignKey("MessageId")
+                        .HasConstraintName("FK_MessageReadRecord_Message")
+                        .IsRequired();
+
+                    b.HasOne("wispro.sp.entity.Message", null)
+                        .WithMany("To")
+                        .HasForeignKey("MessageId1");
+
+                    b.HasOne("wispro.sp.entity.Staff", "Staff")
+                        .WithMany()
+                        .HasForeignKey("StaffId")
+                        .HasConstraintName("FK_MessageReadRecord_Staff")
+                        .IsRequired();
+
+                    b.Navigation("Message");
+
+                    b.Navigation("Staff");
+                });
+
             modelBuilder.Entity("wispro.sp.entity.PerformanceItem", b =>
                 {
+                    b.HasOne("wispro.sp.entity.CalMonth", "CalMonth")
+                        .WithMany("PerformanceItems")
+                        .HasForeignKey("CalMonthId")
+                        .HasConstraintName("FK_PerformanceItem_CalMonth")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
                     b.HasOne("wispro.sp.entity.Customer", "Customer")
                         .WithMany("PerformanceItems")
                         .HasForeignKey("CustomerId")
@@ -581,6 +795,8 @@ namespace wispro.sp.api.Migrations
                         .WithMany("PerformanceItems")
                         .HasForeignKey("StaffId");
 
+                    b.Navigation("CalMonth");
+
                     b.Navigation("Customer");
 
                     b.Navigation("PreOastaff");
@@ -618,11 +834,23 @@ namespace wispro.sp.api.Migrations
                     b.Navigation("DoPerson");
                 });
 
+            modelBuilder.Entity("wispro.sp.entity.CalMonth", b =>
+                {
+                    b.Navigation("PerformanceItems");
+                });
+
             modelBuilder.Entity("wispro.sp.entity.Customer", b =>
                 {
                     b.Navigation("PerformanceItems");
                 });
 
+            modelBuilder.Entity("wispro.sp.entity.Message", b =>
+                {
+                    b.Navigation("RelatedItem");
+
+                    b.Navigation("To");
+                });
+
             modelBuilder.Entity("wispro.sp.entity.PerformanceItem", b =>
                 {
                     b.Navigation("ItemStaffs");

+ 19 - 2
wispro.sp.api/spDbContext.cs

@@ -17,6 +17,7 @@ namespace wispro.sp.api
         {
         }
 
+        public virtual DbSet<CalMonth> CalMonths { get; set; }
         public virtual DbSet<Customer> Customers { get; set; }
         public virtual DbSet<ItemStaff> ItemStaffs { get; set; }
         public virtual DbSet<PerformanceItem> PerformanceItems { get; set; }
@@ -32,6 +33,8 @@ namespace wispro.sp.api
 
         public virtual DbSet<AttachFile> AttachFiles { get; set; }
 
+        public virtual DbSet<BasePointRule> BasePointRules { get; set; }
+
         protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
         {
             if (!optionsBuilder.IsConfigured)
@@ -43,7 +46,17 @@ namespace wispro.sp.api
 
         protected override void OnModelCreating(ModelBuilder modelBuilder)
         {
+            modelBuilder.Entity<CalMonth>(entity =>
+                {
+                    entity.ToTable("CalMonth");
+
+                    entity.Property(e => e.Year).HasColumnName("year");
+
+                    entity.Property(e => e.Month).HasColumnName("month");
 
+                    entity.Property(e => e.Status).HasColumnName("status");
+                }
+            ) ;
             modelBuilder.Entity<Customer>(entity =>
             {
                 entity.ToTable("Customer");
@@ -134,8 +147,7 @@ namespace wispro.sp.api
                 entity.Property(e => e.PreOastaffId).HasColumnName("PreOAStaffId");
 
                 entity.Property(e => e.ReturnDate).HasColumnType("date");
-
-                entity.Property(e => e.Status).HasColumnName("status");
+                
 
                 entity.HasOne(d => d.Customer)
                     .WithMany(p => p.PerformanceItems)
@@ -151,6 +163,11 @@ namespace wispro.sp.api
                     .WithMany(p => p.ReviewerItems)
                     .HasForeignKey(d => d.ReviewerId)
                     .HasConstraintName("FK_PerformanceItem_Reviewer");
+
+                entity.HasOne(d => d.CalMonth)
+                    .WithMany(p => p.PerformanceItems)
+                    .HasForeignKey(d => d.CalMonthId)
+                    .HasConstraintName("FK_PerformanceItem_CalMonth");
             });
 
             modelBuilder.Entity<StaffGrade>(entity =>

+ 1 - 0
wispro.sp.api/wispro.sp.api.csproj

@@ -13,6 +13,7 @@
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
     </PackageReference>
     <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.9" />
+    <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
   </ItemGroup>
 
   <ItemGroup>

+ 16 - 0
wispro.sp.share/UploadResult.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace wispro.sp.share
+{
+    public class UploadResult
+    {
+        public bool Uploaded { get; set; }
+        public string FileName { get; set; }
+        public string StoredFileName { get; set; }
+        public int ErrorCode { get; set; }
+    }
+}

+ 19 - 0
wispro.sp.share/ViewDataUploadFilesResult.cs

@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace wispro.sp.share
+{
+    public class ViewDataUploadFilesResult
+    {
+        public string name { get; set; }
+        public int size { get; set; }
+        public string type { get; set; }
+        public string url { get; set; }
+        public string delete_url { get; set; }
+        public string thumbnail_url { get; set; }
+        public string delete_type { get; set; }
+    }
+}

+ 165 - 31
wispro.sp.web/Pages/UploadData.razor

@@ -5,7 +5,12 @@
 @using System.ComponentModel
 @using AntDesign.TableModels
 @using AntDesign.Form
- 
+@using System.Linq
+@using System.Net.Http.Headers
+@using Microsoft.Extensions.Logging
+@inject HttpClient Http
+@inject ILogger<UploadData> Logger
+@using wispro.sp.share
 
 
 <style>
@@ -24,46 +29,76 @@
     }
 </style>
 
-    <Form Model="@model" LabelColSpan="10" WrapperColSpan="16" style="margin-left: 50px;margin-right:50px;">
+<Form Model="@model" LabelColSpan="10" WrapperColSpan="16" style="margin-left: 50px;margin-right:50px;">
 
-        
-        <wispro.sp.web.Share.SPStep CurrentStep="0" />
 
+    <wispro.sp.web.Share.SPStep CurrentStep="0" />
 
-        <div class=" ant-upload ant-upload-select-text ant-upload-drag ant-upload-select">
 
+    <div class=" ant-upload ant-upload-select-text ant-upload-drag ant-upload-select">
 
-            <FormItem>
-                <p />
-            </FormItem>
-            <FormItem Label="绩效月份" LabelColSpan="10" WrapperColSpan="5">
-                <DatePicker TValue="DateTime?" Picker="@DatePickerType.Month" @bind-Value="@context.Month" />
-            </FormItem>
 
+        <FormItem>
+            <p />
+        </FormItem>
+        <FormItem Label="绩效月份" LabelColSpan="10" WrapperColSpan="5">
+            <DatePicker TValue="DateTime?" Picker="@DatePickerType.Month" @bind-Value="@context.Month" />
+        </FormItem>
+
+
+        <div tabindex="0" class="ant-upload" style="position:relative;" data-fileid="5c8e2c2b-92b2-4b57-bac4-89c3f44c64d4" role="button" _bl_1728="">
+            <Upload Action="http://localhost:39476/api/AttachFiles/PostFile" Name="file">
+                <p class="ant-upload-drag-icon">
+                    <Icon Type="upload" />
+                </p>
+                <p class="ant-upload-text">请选择包括绩效事项记录的Excel文件</p>
+                <p class="ant-upload-hint">
+                    请从维德流程管理系统中导出上月的申请案件完成事项报表文件,并将其上传到系统开始绩效核算流程
+                </p>
+            </Upload>
+            <div class="file-input-zone">
+                <InputFile OnChange="OnInputFileChange" multiple />
+                Get me a file!
+            </div>
+            
+        </div>
 
-            <div tabindex="0" class="ant-upload" style="position:relative;" data-fileid="5c8e2c2b-92b2-4b57-bac4-89c3f44c64d4" role="button" _bl_1728="">
-                <Upload Action="" Name="file">
-                    <p class="ant-upload-drag-icon">
-                        <Icon Type="upload" />
-                    </p>
-                    <p class="ant-upload-text">请选择包括绩效事项记录的Excel文件</p>
-                    <p class="ant-upload-hint">
-                        请从维德流程管理系统中导出上月的申请案件完成事项报表文件,并将其上传到系统开始绩效核算流程
-                    </p>
-                </Upload>
+        <p />
+        <FormItem LabelColSpan="20" WrapperColSpan="16">
+            <Button Type="@ButtonType.Primary" HtmlType="submit">
+                上传
+            </Button>
+        </FormItem>
+    </div>
 
-            </div>
 
-            <p />
-            <FormItem LabelColSpan="20" WrapperColSpan="16">
-                <Button Type="@ButtonType.Primary" HtmlType="submit">
-                    上传
-                </Button>
-            </FormItem>
-        </div>
+</Form>
 
+<style>
+    .file-input-zone {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        background-color: blue;
+        color: white;
+        cursor: pointer;
+        position: relative;
+        width: 120px;
+        height: 30px;
+    }
 
-    </Form>
+        .file-input-zone:hover {
+            background-color: lightblue;
+        }
+
+        .file-input-zone input[type=file] {
+            position: absolute;
+            width: 100%;
+            height: 100%;
+            opacity: 0;
+            cursor: pointer;
+        }
+</style>
 
 @code {
     public class Model
@@ -72,7 +107,7 @@
 
     }
 
-    
+
     private Model model = new Model();
 
     private void OnFinish(EditContext editContext)
@@ -84,4 +119,103 @@
     {
         //Console.WriteLine($"Failed:{JsonSerializer.Serialize(model)}");
     }
+
+    private List<File> files = new();
+    private List<UploadResult> uploadResults = new();
+    private int maxAllowedFiles = 3;
+    private bool shouldRender;
+
+    protected override bool ShouldRender() => shouldRender;
+
+    private async void OnSingleCompleted(AntDesign.UploadInfo uploadInfo)
+    {
+        long maxFileSize = 1024 * 1024 * 15;
+
+        //Stream fs = uploadInfo.File.OpenReadStream(maxFileSize);
+        //await fs.CopyToAsync(memoryStream);
+        //Assembly assembly = Assembly.Load(memoryStream.ToArray());
+    }
+
+    private async System.Threading.Tasks.Task OnInputFileChange(InputFileChangeEventArgs e)
+    {
+        shouldRender = false;
+        long maxFileSize = 1024 * 1024 * 15;
+        var upload = false;
+
+        using var content = new MultipartFormDataContent();
+
+
+        foreach (var file in  e.GetMultipleFiles(maxAllowedFiles))
+        {
+            if (uploadResults.SingleOrDefault(
+                f => f.FileName == file.Name) is null)
+            {
+                try
+                {
+                    var fileContent =
+                        new StreamContent(file.OpenReadStream(maxFileSize));
+
+                    fileContent.Headers.ContentType =
+                        new MediaTypeHeaderValue(file.ContentType);
+
+                    files.Add(new() { Name = file.Name });
+
+                    content.Add(
+                        content: fileContent,
+                        name: "\"files\"",
+                        fileName: file.Name);
+
+                    upload = true;
+                }
+                catch (Exception ex)
+                {
+                    Logger.LogInformation(
+                        "{FileName} not uploaded (Err: 6): {Message}",
+                        file.Name, ex.Message);
+
+                    uploadResults.Add(
+                        new()
+                        {
+                            FileName = file.Name,
+                            ErrorCode = 6,
+                            Uploaded = false
+                        });
+                }
+            }
+        }
+
+        if (upload)
+        {
+            var response = await Http.PostAsync("http://localhost:39476/api/AttachFiles/PostFile", content);
+
+            var newUploadResults = await response.Content
+                .ReadFromJsonAsync<IList<UploadResult>>();
+
+            uploadResults = uploadResults.Concat(newUploadResults).ToList();
+        }
+
+        shouldRender = true;
+
+
+    }
+
+    private static bool FileUpload(IList<UploadResult> uploadResults,
+        string fileName, ILogger<UploadData> logger, out UploadResult result)
+    {
+        result = uploadResults.SingleOrDefault(f => f.FileName == fileName);
+
+        if (result is null)
+        {
+            logger.LogInformation("{FileName} not uploaded (Err: 5)", fileName);
+            result = new();
+            result.ErrorCode = 5;
+        }
+
+        return result.Uploaded;
+    }
+
+    private class File
+    {
+        public string Name { get; set; }
+    }
 }

+ 4 - 0
wispro.sp.web/wispro.sp.web.csproj

@@ -19,6 +19,10 @@
     <PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="5.0.9" />
     <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.0" />
     <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.0" PrivateAssets="all" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.11">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+    </PackageReference>
     <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
     <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.6.0" />
     <PackageReference Include="System.Net.Http.Json" Version="5.0.0" />

+ 1 - 1
wispro.sp.web/wwwroot/appsettings.json

@@ -14,6 +14,6 @@
     "MenuRender": true,
     "MenuHeaderRender": true,
     "HeaderHeight": 48
-    
+
   }
 }

+ 10 - 5
wispro.sp.winClient/Form1.cs

@@ -54,6 +54,7 @@ namespace wispro.sp.winClient
 
         private async void button3_Click(object sender, EventArgs e)
         {
+            //await NewMethod();
             await InputPerformanceItem();
         }
 
@@ -69,8 +70,10 @@ namespace wispro.sp.winClient
                 item.CaseNo = row["我方文号"].ToString().Trim();
                 string strjxyf = row["绩效核算月份"].ToString().Trim();
                 string[] temYFs = strjxyf.Split(new char[] { '.' });
-                item.Year = int.Parse(temYFs[0]);
-                item.Month = int.Parse(temYFs[1]);
+                item.CalMonth = new CalMonth();
+                item.CalMonth.Year = int.Parse(temYFs[0]);
+                item.CalMonth.Month = int.Parse(temYFs[1]);
+                item.CalMonth.Status = 4;
 
                 item.ApplicationType = row["申请类型"].ToString().Trim();
                 item.BusinessType = row["业务类型"].ToString().Trim();
@@ -98,7 +101,7 @@ namespace wispro.sp.winClient
                     else
                     {
                         itemStaff.DoPerson = new Staff() { Name = name,
-                            Account = name,
+                            Account =name,
                             Password = "12345678",
                             IsCalPerformsnce = false,
                             Status = "已离职",
@@ -184,9 +187,11 @@ namespace wispro.sp.winClient
         {
             if (!string.IsNullOrEmpty(v))
             {
-                foreach(Staff sf in staffs)
+                string[] temNames = v.Trim().Split(new char[] { '-' },StringSplitOptions.RemoveEmptyEntries);
+
+                foreach (Staff sf in staffs)
                 {
-                    if(sf.Name == v)
+                    if(sf.Name == temNames[0])
                     {
                         return sf.Id;
                     }

+ 26 - 0
wospro.sp.entity/BasePointRule.cs

@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace wispro.sp.entity
+{
+    /// <summary>
+    /// 基础点数规则
+    /// </summary>
+    public class BasePointRule
+    {
+        public int Id { get; set; }
+
+        /// <summary>
+        /// 基础点数规则
+        /// </summary>
+        public string Rule { get; set; }
+
+        /// <summary>
+        /// 基础点数
+        /// </summary>
+        public double Point { get; set; }
+    }
+}

+ 37 - 0
wospro.sp.entity/CalMonth.cs

@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace wispro.sp.entity
+{
+    public class CalMonth
+    {
+        /// <summary>
+        /// 编号
+        /// </summary>
+        public int Id { get; set; }
+
+        /// <summary>
+        /// 绩效年度
+        /// </summary>
+        public int Year { get; set; }
+
+        /// <summary>
+        /// 绩效月份
+        /// </summary>
+        public int Month { get; set; }
+
+        /// <summary>
+        /// 绩效状态
+        /// 0:新导入
+        /// 1:代理人反馈
+        /// 2:计算绩效中
+        /// 3:已完成
+        /// </summary>
+        public int Status { get; set; }
+
+        public virtual List<PerformanceItem> PerformanceItems { get; set; }
+    }
+}

+ 12 - 8
wospro.sp.entity/PerformanceItem.cs

@@ -23,15 +23,15 @@ namespace wispro.sp.entity
         
         public int Id { get; set; }
 
-        /// <summary>
-        /// 绩效计算年度
-        /// </summary>
-        public int Year { get; set; }
+        ///// <summary>
+        ///// 绩效计算年度
+        ///// </summary>
+        //public int Year { get; set; }
 
-        /// <summary>
-        /// 绩效计算月份
-        /// </summary>
-        public int Month { get; set; }
+        ///// <summary>
+        ///// 绩效计算月份
+        ///// </summary>
+        //public int Month { get; set; }
 
         /// <summary>
         /// 我方文号
@@ -190,6 +190,10 @@ namespace wispro.sp.entity
         /// </summary>
         public virtual Staff Reviewer { get; set; }
 
+        public virtual CalMonth CalMonth { get; set; }
+
+        public int CalMonthId { get; set; }
+
         public bool isDanger()
         {
             if (DoItem.ToString() == "新申请")

+ 2 - 1
wospro.sp.entity/workflowDefine/step.cs

@@ -39,7 +39,8 @@ namespace wispro.sp.entity.workflowDefine
         /// 0:启动
         /// 1:普通
         /// 2:合并
-        /// 3:完成
+        /// 3:分支
+        /// 4:完成
         /// </summary>
         public int stepType { get; set; }