JaneDoe преди 3 месеца
родител
ревизия
4032945b15

+ 6 - 8
UniformMaterialManagementSystem/Entities/Material.cs

@@ -1,4 +1,5 @@
 using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
 
 namespace UniformMaterialManagementSystem.Entities
 {
@@ -14,10 +15,6 @@ namespace UniformMaterialManagementSystem.Entities
         [StringLength(50)]
         public string Name { get; set; } = null!;
 
-        [Required]
-        [StringLength(50)]
-        public string ShortName { get; set; } = null!;
-
         [Required]
         [StringLength(50)]
         public string VarietyCode { get; set; } = null!;
@@ -26,9 +23,6 @@ namespace UniformMaterialManagementSystem.Entities
         [StringLength(50)]
         public string CategoryCode { get; set; } = null!;
 
-        [StringLength(50)]
-        public string? NormName { get; set; }
-
         [Required]
         [StringLength(50)]
         public string Specification { get; set; } = null!;
@@ -37,13 +31,17 @@ namespace UniformMaterialManagementSystem.Entities
         [StringLength(50)]
         public string MeasureUnit { get; set; } = null!;
 
-        public byte[]? Photo { get; set; }
+        [StringLength(50)]
+        public string? NormName { get; set; }
 
         [StringLength(100)]
         public string? Note { get; set; }
 
         public bool IsEnabled { get; set; } = true;
 
+        [NotMapped]
+        public bool IsNewRow { get; set; } = true;
+
         public Material() { }
     }
 }

+ 883 - 0
UniformMaterialManagementSystem/Migrations/20240718091921_delete_MaterialFields.Designer.cs

@@ -0,0 +1,883 @@
+// <auto-generated />
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using UniformMaterialManagementSystem.Data;
+
+#nullable disable
+
+namespace UniformMaterialManagementSystem.Migrations
+{
+    [DbContext(typeof(SqliteContext))]
+    [Migration("20240718091921_delete_MaterialFields")]
+    partial class delete_MaterialFields
+    {
+        /// <inheritdoc />
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder.HasAnnotation("ProductVersion", "7.0.20");
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.Company", b =>
+                {
+                    b.Property<Guid>("Guid")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Address")
+                        .HasMaxLength(100)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Category")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Code")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<bool>("IsEnabled")
+                        .HasColumnType("INTEGER");
+
+                    b.Property<string>("Manager")
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Note")
+                        .HasMaxLength(100)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ShortName")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("SystemCode")
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.HasKey("Guid");
+
+                    b.ToTable("Companies");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.Contract", b =>
+                {
+                    b.Property<Guid>("Guid")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("TEXT");
+
+                    b.Property<byte[]>("Attachment")
+                        .HasColumnType("BLOB");
+
+                    b.Property<Guid>("CompanyGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ContractNo")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<DateTime>("EditDate")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("EditUser")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<bool>("ExportStatus")
+                        .HasColumnType("INTEGER");
+
+                    b.Property<Guid>("PurchaseCompanyGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<DateTime>("SigningDate")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Telephone")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.HasKey("Guid");
+
+                    b.HasIndex("CompanyGuid");
+
+                    b.HasIndex("PurchaseCompanyGuid");
+
+                    b.ToTable("Contracts");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.ContractDetail", b =>
+                {
+                    b.Property<Guid>("Guid")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("TEXT");
+
+                    b.Property<Guid>("ContractGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<double>("ContractQty")
+                        .HasColumnType("REAL");
+
+                    b.Property<DateTime>("DeliveryTime")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("InspectStatus")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<double>("InspectedQty")
+                        .HasColumnType("REAL");
+
+                    b.Property<Guid>("MaterialGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<double>("ShippedQuantity")
+                        .HasColumnType("REAL");
+
+                    b.Property<double>("UnitPrice")
+                        .HasColumnType("REAL");
+
+                    b.HasKey("Guid");
+
+                    b.HasIndex("ContractGuid");
+
+                    b.HasIndex("MaterialGuid");
+
+                    b.ToTable("ContractDetails");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.DeliveryReceipt", b =>
+                {
+                    b.Property<Guid>("Guid")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("TEXT");
+
+                    b.Property<Guid>("ApplyGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("BatchNo")
+                        .IsRequired()
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("CompanyName")
+                        .IsRequired()
+                        .HasColumnType("TEXT");
+
+                    b.Property<Guid>("ContractGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ContractNo")
+                        .IsRequired()
+                        .HasColumnType("TEXT");
+
+                    b.Property<decimal>("ContractQty")
+                        .HasColumnType("TEXT");
+
+                    b.Property<DateTime>("ContractSigningDate")
+                        .HasColumnType("TEXT");
+
+                    b.Property<byte[]>("Licence")
+                        .HasColumnType("BLOB");
+
+                    b.Property<string>("MaterialName")
+                        .IsRequired()
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ProductCompanyName")
+                        .IsRequired()
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ReceivedCompanyName")
+                        .IsRequired()
+                        .HasColumnType("TEXT");
+
+                    b.Property<DateTime?>("ReceivedDate")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ReceivedMan")
+                        .HasColumnType("TEXT");
+
+                    b.Property<int?>("ReceivedPackets")
+                        .HasColumnType("INTEGER");
+
+                    b.Property<decimal?>("ReceivedQty")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ReceivedStatus")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ReceivedTel")
+                        .HasColumnType("TEXT");
+
+                    b.Property<DateTime>("ShippedDate")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ShippedMan")
+                        .HasColumnType("TEXT");
+
+                    b.Property<int>("ShippedPackets")
+                        .HasColumnType("INTEGER");
+
+                    b.Property<decimal>("ShippedQty")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ShippedTel")
+                        .HasColumnType("TEXT");
+
+                    b.HasKey("Guid");
+
+                    b.ToTable("DeliveryReceipts");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.DeliveryReceiptDetail", b =>
+                {
+                    b.Property<Guid>("Guid")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("TEXT");
+
+                    b.Property<Guid>("DeliveryReceiptGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("PacketNo")
+                        .IsRequired()
+                        .HasColumnType("TEXT");
+
+                    b.Property<decimal?>("ReceiveQuantity")
+                        .HasColumnType("TEXT");
+
+                    b.Property<decimal>("ShippedQuantity")
+                        .HasColumnType("TEXT");
+
+                    b.Property<decimal?>("UseQuantity")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("UseStatus")
+                        .HasColumnType("TEXT");
+
+                    b.HasKey("Guid");
+
+                    b.HasIndex("DeliveryReceiptGuid");
+
+                    b.ToTable("DeliveryReceiptDetails");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.InspectApply", b =>
+                {
+                    b.Property<Guid>("Guid")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ApplyDescription")
+                        .HasMaxLength(1000)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ApplyNo")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<DateTime?>("ApplyReceiveDate")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ApplyUser")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Company")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<Guid>("CompanyGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<DateTime>("EndProductDate")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("InspCategory")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<DateTime>("InspDate")
+                        .HasColumnType("TEXT");
+
+                    b.Property<double>("InspQuantity")
+                        .HasColumnType("REAL");
+
+                    b.Property<byte[]>("InspReport")
+                        .HasColumnType("BLOB");
+
+                    b.Property<Guid>("MaterialGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ProductName")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<bool>("ReportStatus")
+                        .HasColumnType("INTEGER");
+
+                    b.Property<DateTime>("StartProductDate")
+                        .HasColumnType("TEXT");
+
+                    b.Property<int>("Year")
+                        .HasColumnType("INTEGER");
+
+                    b.HasKey("Guid");
+
+                    b.HasIndex("CompanyGuid");
+
+                    b.HasIndex("MaterialGuid");
+
+                    b.ToTable("InspectApplies");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.InspectApplyContractDetail", b =>
+                {
+                    b.Property<Guid>("Guid")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("TEXT");
+
+                    b.Property<Guid>("ApplyGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ApplyNo")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<Guid>("ContractDetailGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ContractNo")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<double>("InspectQty")
+                        .HasColumnType("REAL");
+
+                    b.Property<string>("PurchaseCompany")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("SigningDate")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<double>("UnInspectQty")
+                        .HasColumnType("REAL");
+
+                    b.HasKey("Guid");
+
+                    b.HasIndex("ApplyGuid");
+
+                    b.ToTable("InspectApplyContractDetails");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.InspectApplyDetail", b =>
+                {
+                    b.Property<Guid>("Guid")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("TEXT");
+
+                    b.Property<Guid>("ApplyGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ApplyNo")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("BatchNo")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Note")
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("PacketNo")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<double>("Quantity")
+                        .HasColumnType("REAL");
+
+                    b.HasKey("Guid");
+
+                    b.HasIndex("ApplyGuid");
+
+                    b.ToTable("InspectApplyDetails");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.Material", b =>
+                {
+                    b.Property<Guid>("Guid")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("CategoryCode")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<bool>("IsEnabled")
+                        .HasColumnType("INTEGER");
+
+                    b.Property<string>("MeasureUnit")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("NormName")
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Note")
+                        .HasMaxLength(100)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Specification")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("VarietyCode")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.HasKey("Guid");
+
+                    b.ToTable("Materials");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.MenuItem", b =>
+                {
+                    b.Property<Guid>("Guid")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Icon")
+                        .HasMaxLength(100)
+                        .HasColumnType("TEXT");
+
+                    b.Property<bool>("IsEnabled")
+                        .HasColumnType("INTEGER");
+
+                    b.Property<bool>("IsVisible")
+                        .HasColumnType("INTEGER");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<int>("OrderIndex")
+                        .HasColumnType("INTEGER");
+
+                    b.Property<Guid?>("ParentGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Path")
+                        .HasMaxLength(100)
+                        .HasColumnType("TEXT");
+
+                    b.HasKey("Guid");
+
+                    b.HasIndex("ParentGuid");
+
+                    b.ToTable("MenuItems");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.Role", b =>
+                {
+                    b.Property<Guid>("Guid")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Description")
+                        .IsRequired()
+                        .HasMaxLength(100)
+                        .HasColumnType("TEXT");
+
+                    b.Property<bool>("IsEnabled")
+                        .HasColumnType("INTEGER");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.HasKey("Guid");
+
+                    b.ToTable("Roles");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.RoleMenuItem", b =>
+                {
+                    b.Property<Guid>("MenuItemGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<Guid>("RoleGuid")
+                        .HasColumnType("TEXT");
+
+                    b.HasKey("MenuItemGuid", "RoleGuid");
+
+                    b.HasIndex("RoleGuid");
+
+                    b.ToTable("RoleMenuItems");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.SerialNumber", b =>
+                {
+                    b.Property<Guid>("Guid")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("CompanyCode")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<Guid>("CompanyGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("InspCategory")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("MaxNumber")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<Guid>("SupervisionUnitGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<int>("Year")
+                        .HasColumnType("INTEGER");
+
+                    b.HasKey("Guid");
+
+                    b.ToTable("SerialNumbers");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.SupervisionUnit", b =>
+                {
+                    b.Property<Guid>("Guid")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("TEXT");
+
+                    b.Property<bool>("IsEnabled")
+                        .HasColumnType("INTEGER");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Note")
+                        .HasMaxLength(100)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("ShortName")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.HasKey("Guid");
+
+                    b.ToTable("SupervisionUnits");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.User", b =>
+                {
+                    b.Property<Guid>("Guid")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("TEXT");
+
+                    b.Property<Guid?>("CompanyGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("CompanyName")
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("IdNumber")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<bool>("IsEnabled")
+                        .HasColumnType("INTEGER");
+
+                    b.Property<string>("LoginName")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Password")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<DateTime>("RegisterDate")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("Salt")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.Property<Guid>("SupervisionUnitGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("UserName")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("TEXT");
+
+                    b.HasKey("Guid");
+
+                    b.HasIndex("CompanyGuid");
+
+                    b.HasIndex("SupervisionUnitGuid");
+
+                    b.ToTable("Users");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.UserRole", b =>
+                {
+                    b.Property<Guid>("RoleGuid")
+                        .HasColumnType("TEXT");
+
+                    b.Property<Guid>("UserGuid")
+                        .HasColumnType("TEXT");
+
+                    b.HasKey("RoleGuid", "UserGuid");
+
+                    b.HasIndex("UserGuid");
+
+                    b.ToTable("UserRoles");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.Contract", b =>
+                {
+                    b.HasOne("UniformMaterialManagementSystem.Entities.Company", "Company")
+                        .WithMany()
+                        .HasForeignKey("CompanyGuid")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("UniformMaterialManagementSystem.Entities.Company", "PurchaseCompany")
+                        .WithMany()
+                        .HasForeignKey("PurchaseCompanyGuid")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Company");
+
+                    b.Navigation("PurchaseCompany");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.ContractDetail", b =>
+                {
+                    b.HasOne("UniformMaterialManagementSystem.Entities.Contract", "Contract")
+                        .WithMany("ContractDetails")
+                        .HasForeignKey("ContractGuid")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("UniformMaterialManagementSystem.Entities.Material", "Material")
+                        .WithMany()
+                        .HasForeignKey("MaterialGuid")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Contract");
+
+                    b.Navigation("Material");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.DeliveryReceiptDetail", b =>
+                {
+                    b.HasOne("UniformMaterialManagementSystem.Entities.DeliveryReceipt", null)
+                        .WithMany("DeliveryReceiptDetails")
+                        .HasForeignKey("DeliveryReceiptGuid")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.InspectApply", b =>
+                {
+                    b.HasOne("UniformMaterialManagementSystem.Entities.Company", "MaterialCompany")
+                        .WithMany()
+                        .HasForeignKey("CompanyGuid")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("UniformMaterialManagementSystem.Entities.Material", "Material")
+                        .WithMany()
+                        .HasForeignKey("MaterialGuid")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Material");
+
+                    b.Navigation("MaterialCompany");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.InspectApplyContractDetail", b =>
+                {
+                    b.HasOne("UniformMaterialManagementSystem.Entities.InspectApply", "InspectApply")
+                        .WithMany("InspectApplyContractDetails")
+                        .HasForeignKey("ApplyGuid")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("InspectApply");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.InspectApplyDetail", b =>
+                {
+                    b.HasOne("UniformMaterialManagementSystem.Entities.InspectApply", "InspectApply")
+                        .WithMany("InspectApplyDetails")
+                        .HasForeignKey("ApplyGuid")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("InspectApply");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.MenuItem", b =>
+                {
+                    b.HasOne("UniformMaterialManagementSystem.Entities.MenuItem", "Parent")
+                        .WithMany("Children")
+                        .HasForeignKey("ParentGuid")
+                        .OnDelete(DeleteBehavior.Restrict);
+
+                    b.Navigation("Parent");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.RoleMenuItem", b =>
+                {
+                    b.HasOne("UniformMaterialManagementSystem.Entities.MenuItem", "MenuItem")
+                        .WithMany("MenuRoles")
+                        .HasForeignKey("MenuItemGuid")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("UniformMaterialManagementSystem.Entities.Role", "Role")
+                        .WithMany("RoleMenus")
+                        .HasForeignKey("RoleGuid")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("MenuItem");
+
+                    b.Navigation("Role");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.User", b =>
+                {
+                    b.HasOne("UniformMaterialManagementSystem.Entities.Company", "Company")
+                        .WithMany()
+                        .HasForeignKey("CompanyGuid");
+
+                    b.HasOne("UniformMaterialManagementSystem.Entities.SupervisionUnit", "SupervisionUnit")
+                        .WithMany()
+                        .HasForeignKey("SupervisionUnitGuid")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Company");
+
+                    b.Navigation("SupervisionUnit");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.UserRole", b =>
+                {
+                    b.HasOne("UniformMaterialManagementSystem.Entities.Role", "Role")
+                        .WithMany("UserRoles")
+                        .HasForeignKey("RoleGuid")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("UniformMaterialManagementSystem.Entities.User", "User")
+                        .WithMany("UserRoles")
+                        .HasForeignKey("UserGuid")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Role");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.Contract", b =>
+                {
+                    b.Navigation("ContractDetails");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.DeliveryReceipt", b =>
+                {
+                    b.Navigation("DeliveryReceiptDetails");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.InspectApply", b =>
+                {
+                    b.Navigation("InspectApplyContractDetails");
+
+                    b.Navigation("InspectApplyDetails");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.MenuItem", b =>
+                {
+                    b.Navigation("Children");
+
+                    b.Navigation("MenuRoles");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.Role", b =>
+                {
+                    b.Navigation("RoleMenus");
+
+                    b.Navigation("UserRoles");
+                });
+
+            modelBuilder.Entity("UniformMaterialManagementSystem.Entities.User", b =>
+                {
+                    b.Navigation("UserRoles");
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}

+ 40 - 0
UniformMaterialManagementSystem/Migrations/20240718091921_delete_MaterialFields.cs

@@ -0,0 +1,40 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace UniformMaterialManagementSystem.Migrations
+{
+    /// <inheritdoc />
+    public partial class delete_MaterialFields : Migration
+    {
+        /// <inheritdoc />
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropColumn(
+                name: "Photo",
+                table: "Materials");
+
+            migrationBuilder.DropColumn(
+                name: "ShortName",
+                table: "Materials");
+        }
+
+        /// <inheritdoc />
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AddColumn<byte[]>(
+                name: "Photo",
+                table: "Materials",
+                type: "BLOB",
+                nullable: true);
+
+            migrationBuilder.AddColumn<string>(
+                name: "ShortName",
+                table: "Materials",
+                type: "TEXT",
+                maxLength: 50,
+                nullable: false,
+                defaultValue: "");
+        }
+    }
+}

+ 0 - 8
UniformMaterialManagementSystem/Migrations/SqliteContextModelSnapshot.cs

@@ -601,14 +601,6 @@ namespace UniformMaterialManagementSystem.Migrations
                         .HasMaxLength(100)
                         .HasColumnType("TEXT");
 
-                    b.Property<byte[]>("Photo")
-                        .HasColumnType("BLOB");
-
-                    b.Property<string>("ShortName")
-                        .IsRequired()
-                        .HasMaxLength(50)
-                        .HasColumnType("TEXT");
-
                     b.Property<string>("Specification")
                         .IsRequired()
                         .HasMaxLength(50)

+ 0 - 74
UniformMaterialManagementSystem/Models/MaterialModel.cs

@@ -1,74 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations.Schema;
-using System.ComponentModel.DataAnnotations;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using CommunityToolkit.Mvvm.ComponentModel;
-using UniformMaterialManagementSystem.Entities;
-
-namespace UniformMaterialManagementSystem.Models
-{
-    public partial class MaterialModel : ObservableObject
-    {
-        [ObservableProperty]
-        private Guid _guid;
-
-        [ObservableProperty]
-        private string _name = null!;
-
-        [ObservableProperty]
-        private string _shortName = null!;
-
-        [ObservableProperty]
-        private string _varietyCode = null!;
-
-        [ObservableProperty]
-        private string _categoryCode = null!;
-
-        [ObservableProperty]
-        private string? _normName;
-
-        [ObservableProperty]
-        private string _specification = null!;
-
-        [ObservableProperty]
-        private string _measureUnit = null!;
-
-        [ObservableProperty]
-        private byte[]? _photo;
-
-        [ObservableProperty]
-        private string? _note;
-
-        [ObservableProperty]
-        private bool _isEnabled = true;
-
-        // todo 是否需要 NotMapped 注解?
-        [NotMapped]
-        [ObservableProperty]
-        private bool _isNewRow = true;
-
-        [NotMapped]
-        [ObservableProperty]
-        private string? _uploadSign;
-
-        public MaterialModel(Material material, bool isNewRow, string? uploadSign)
-        {
-            Guid = material.Guid;
-            Name = material.Name;
-            ShortName = material.ShortName;
-            VarietyCode = material.VarietyCode;
-            CategoryCode = material.CategoryCode;
-            NormName = material.NormName;
-            Specification = material.Specification;
-            MeasureUnit = material.MeasureUnit;
-            Photo = material.Photo;
-            Note = material.Note;
-            IsEnabled = material.IsEnabled;
-            IsNewRow = isNewRow;
-            UploadSign = uploadSign;
-        }
-    }
-}

+ 295 - 0
UniformMaterialManagementSystem/Utils/OpenXmlExcelUtil.cs

@@ -0,0 +1,295 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using DocumentFormat.OpenXml.Packaging;
+using DocumentFormat.OpenXml.Spreadsheet;
+using DocumentFormat.OpenXml;
+using System.Data;
+using System.IO;
+using Microsoft.EntityFrameworkCore.Metadata.Internal;
+
+namespace UniformMaterialManagementSystem.Utils
+{
+    internal class OpenXmlExcelUtil
+    {
+        public void Test(DataTable dt, string filePath)
+        {
+            string fileName = "材料基础数据-" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xlsx";
+
+            // 电子表格文档
+            SpreadsheetDocument spreadsheet = SpreadsheetDocument.Create(fileName, SpreadsheetDocumentType.Workbook); // 表示一个 Excel 文档包
+            // 工作簿:只允许一个实例
+            WorkbookPart workbookPart = spreadsheet.AddWorkbookPart(); // 这是 Excel 文档的顶级容器。只允许一个实例。
+            //        WorkbookPart 的子元素,WorkbookPart 和 Workbook 是一对一关系
+            workbookPart.Workbook = new Workbook();
+            // 工作表:通过 WorkbookPart 对象创建工作表,数量不限。
+            WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
+            //        WorksheetPart 和 Worksheet 一对一,对应Excel文件中的工作表 Sheet
+            worksheetPart.Worksheet = new Worksheet();
+            WorksheetPart worksheetPart2 = workbookPart.AddNewPart<WorksheetPart>();
+            worksheetPart2.Worksheet = new Worksheet();
+            // 工作表数据:行数据,每行多个单元格
+            SheetData sheetData = new SheetData();
+
+            Row row = new Row();
+            for (int i = 0; i < dt.Columns.Count; i++)
+            {
+                DataColumn dc = dt.Columns[i];
+                Cell cell0 = new Cell();
+                cell0.DataType = CellValues.InlineString; // todo SharedString / String / InlineString 三者的异同?
+                cell0.InlineString = new InlineString() { Text = new DocumentFormat.OpenXml.Spreadsheet.Text(dc.Caption) };
+                row.InsertAt<Cell>(cell0, i);
+            }
+
+            sheetData.InsertAt(row, 0);
+
+            // 一个 Workbook 有一个 Sheets 对象。
+            // 添加 Sheets
+            Sheets sheets = spreadsheet.WorkbookPart!.Workbook.AppendChild(new Sheets());
+            // 把 WorkSheet 对象关联到 Workbook
+            sheets.Append(new Sheet()
+            {
+                Id = spreadsheet.WorkbookPart.GetIdOfPart(worksheetPart), // 把 WorkSheet 对象与 Excel 文件中的工作表Sheet关联起来
+                SheetId = 1,
+                Name = "Sheet 1"
+            });
+            sheets.Append(new Sheet()
+            {
+                Id = spreadsheet.WorkbookPart.GetIdOfPart(worksheetPart2),
+                SheetId = 2,
+                Name = "Sheet 2"
+            });
+
+            // 添加行数据
+
+
+        }
+
+        public static void CreateExcel(string excelFilePath, DataTable[] tables, string[] sheetNames)
+        {
+            SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(excelFilePath, SpreadsheetDocumentType.Workbook);
+            WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart();
+            workbookpart.Workbook = new Workbook();
+
+            Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild(new Sheets());
+
+            for (int i = 0; i < tables.Length; i++)
+            {
+                WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
+                worksheetPart.Worksheet = new Worksheet(CreatSheetData(tables[i]));
+
+                Sheet sheet = new Sheet()
+                {
+                    Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart),
+                    SheetId = new UInt32Value((uint)(i + 1)),
+                    Name = (sheetNames != null ? sheetNames[i] : i.ToString())
+                };
+                sheets.Append(sheet);
+            }
+
+            workbookpart.Workbook.Save();
+            spreadsheetDocument.Dispose();
+        }
+
+        public static SheetData CreatSheetData(DataTable table)
+        {
+            var sheetData = new SheetData();
+            for (int r = 0; r < table.Rows.Count; r++)
+            {
+                Row row = new Row();
+                for (int c = 0; c < table.Columns.Count; c++)
+                {
+                    Cell dataCell = new Cell();
+                    dataCell.CellValue = new CellValue(table.Rows[r][c].ToString());
+                    dataCell.DataType = CellValues.String;
+                    row.AppendChild(dataCell);
+                }
+                sheetData.Append(row);
+            }
+            return sheetData;
+        }
+
+
+
+
+        /// <summary>
+        /// 将 Excel 中的数据转换到 DataTable
+        /// </summary>
+        /// <param name="filePath">文件地址</param>
+        /// <returns>DataTable</returns>
+        public static DataTable? ExcelToDataTable(string filePath, string sheetName = "Sheet1")
+        {
+            // 判断文件是否被占用
+            bool isFileLocked = false;
+            try
+            {
+                // 如果能够成功打开文件,说明文件未被占用
+                using FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None);
+                isFileLocked = false;
+            }
+            catch (IOException)
+            {
+                // 如果打开文件时发生IOException异常,说明文件被占用
+                isFileLocked = true;
+            }
+
+            // 如果被占用,复制一份临时文件
+            if (isFileLocked)
+            {
+                int startIndex = filePath.LastIndexOf("\\");
+                int endIndex = filePath.LastIndexOf('.');
+                string fileName = filePath.Substring(startIndex + 1, endIndex - startIndex - 1);
+                string tempPath = filePath.Replace(fileName, fileName + "_Temp");
+
+                //string selectedPath = filePath.Substring(0, startIndex);
+                //string fileType = filePath.Substring(endIndex + 1);
+                //var tempFilePath = $"{selectedPath}\\{fileName}_Temp.{fileType}";
+                File.Copy(filePath, tempPath);
+                filePath = tempPath;
+            }
+
+            // 获取 Excel 数据
+            using SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(filePath, false); // 文件打开时不能访问
+            WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart ?? spreadSheetDocument.AddWorkbookPart();
+            // 获取第一个 Sheet?
+            IEnumerable<Sheet>? sheets = spreadSheetDocument.WorkbookPart?.Workbook.GetFirstChild<Sheets>()?.Elements<Sheet>();
+
+
+            // 查找指定的 Sheet (默认第一个Sheet)
+            //sheetName = "Sheet1";
+            IEnumerable<Sheet>? sheets0 = spreadSheetDocument.WorkbookPart?.Workbook.Descendants<Sheet>().Where(s => s.Name == sheetName);
+            if (sheets == null || sheets.Count() == 0)
+            {
+                // 没有找到 Sheet 则返回
+                return null;
+            }
+
+
+            string? relationshipId = sheets?.First()?.Id;
+            string? relationshipId1 = sheets?.First()?.Id?.Value;
+            string? relationshipId2 = sheets?.First()?.Id.ToString();
+            if (string.IsNullOrEmpty(relationshipId))
+            {
+                // todo 提示获取文件失败?
+                return null;
+            }
+            WorksheetPart? worksheetPart = spreadSheetDocument.WorkbookPart?.GetPartById(relationshipId) as WorksheetPart;
+            Worksheet? workSheet = worksheetPart?.Worksheet;
+            SheetData? sheetData = workSheet?.GetFirstChild<SheetData>();
+
+            // 获得Excel中得数据行
+            IEnumerable<Row>? rows0 = worksheetPart?.Worksheet?.Descendants<Row>(); // todo Worksheet.Descendants<>() 和 sheetData.Descendants<>() 区别?
+            IEnumerable<Row>? rows = sheetData?.Descendants<Row>();
+            if (rows == null || rows.Count() == 0)
+            {
+                return null;
+            }
+
+            int colCnt = rows.ElementAt(0).Count();
+            int rowCnt = rows.Count();
+
+            // 根据第一行的列名构建 DataTable 的列
+            DataTable dt = new DataTable();
+            foreach (Cell cell in rows.ElementAt(0))
+            {
+                dt.Columns.Add(GetCellValue(spreadSheetDocument, cell));
+            }
+
+            // 添加行数据
+            foreach (Row row in rows)
+            {
+                // 跳过第一行
+                if (row == rows.ElementAt(0)) { continue; }
+
+                DataRow dr = dt.NewRow();
+
+                for (int i = 0; i < row.Descendants<Cell>().Count(); i++)
+                {
+                    Cell cell = row.Descendants<Cell>().ElementAt(i);
+
+                    // 会跳过空白单元格左移
+                    //dr[i] = GetCellValue(spreadSheetDocument, cell);
+
+                    int actualCellIndex = CellReferenceToIndex(cell);
+                    dr[actualCellIndex] = GetCellValue(spreadSheetDocument, cell);
+                }
+
+                dt.Rows.Add(dr);
+            }
+
+
+            if (isFileLocked)
+            {
+                File.Delete(filePath);
+            }
+
+            return dt;
+        }
+
+        public static string GetCellValue(SpreadsheetDocument document, Cell cell)
+        {
+
+            if (cell.ChildElements.Count == 0) { return string.Empty; }
+
+            if (cell.CellValue == null) { return string.Empty; }
+
+            string value0 = double.Parse(cell.CellValue!.InnerText).ToString();
+            string value = cell.CellValue!.InnerXml;
+
+
+            // 因为 Excel 的数据存储在 SharedStringTable 中,须要获取数据在 SharedStringTable 中的索引
+            SharedStringTablePart? stringTablePart = document.WorkbookPart?.SharedStringTablePart;
+            if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString)
+            {
+                return stringTablePart!.SharedStringTable.ChildElements[int.Parse(value)].InnerText;
+            }
+            else
+            {
+                return value;
+            }
+        }
+
+        /// <summary>
+        /// 获取任何单元格的原始/正确的列索引
+        /// </summary>
+        /// <param name="cell"></param>
+        /// <returns></returns>
+        private static int CellReferenceToIndex(Cell cell)
+        {
+            int index = 0;
+            string? reference = cell.CellReference?.ToString()?.ToUpper();
+
+            // 方法一:
+            int colIndex = 0;
+            foreach (char ch in reference!)
+            {
+                if (char.IsLetter(ch))
+                {
+                    int value = (int)ch - (int)'A';
+                    colIndex = (index == 0) ? value : ((index + 1) * 26) + value;
+                }
+                else
+                {
+                    return colIndex;
+                }
+            }
+
+            // 方法二:
+            int colIndex2 = 0;
+            int pow = 1;
+            for (int i = reference.Length - 1; i >= 0; i--)
+            {
+                colIndex2 += (reference[i] - 'A' + 1) * pow;
+                pow *= 26;
+            }
+
+
+
+
+
+            return index;
+        }
+    }
+}

+ 27 - 5
UniformMaterialManagementSystem/ViewModels/MaterialCompanyViewModel.cs

@@ -4,6 +4,7 @@ using System.ComponentModel.DataAnnotations;
 using System.Data;
 using System.Security.Cryptography.X509Certificates;
 using System.Text;
+using System.Text.RegularExpressions;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Controls.Primitives;
@@ -126,7 +127,7 @@ namespace UniformMaterialManagementSystem.ViewModels
             if (cells.Count == 0)
             {
                 // 没有选中单元格则提示后返回
-                MessageBox.Show("当前没有选中行,请选中一行后再删除。");
+                MessageBox.Show("当前没有选中行,请选中一行后再删除。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                 return;
             }
 
@@ -143,7 +144,7 @@ namespace UniformMaterialManagementSystem.ViewModels
             // 已保存行询问
             else
             {
-                MessageBoxResult res = MessageBox.Show("是否确定删除当前行?", "Ask", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
+                MessageBoxResult res = MessageBox.Show("是否确定删除当前行?", "询问", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
                 if (res != MessageBoxResult.Yes) { return; }
             }
 
@@ -175,7 +176,7 @@ namespace UniformMaterialManagementSystem.ViewModels
 
             // 检查新增行的必录项是否为空
             var nullCompanies = Companies.Where(x => x.IsNewRow && (string.IsNullOrEmpty(x.Name) || string.IsNullOrEmpty(x.ShortName) || string.IsNullOrEmpty(x.Code) || string.IsNullOrEmpty(x.SystemCode)));
-            if (nullCompanies.Count() > 0)
+            if (nullCompanies.Any())
             {
                 // 如果存在未填的必录项,则提示
                 Dictionary<int, int> nullIndexes = new Dictionary<int, int>(); // 使用 Hashtable 时取键值对的值时会进行拆箱(可能为 null 的 Object 转换为 int),换成 Dictionary<int, int>
@@ -198,7 +199,7 @@ namespace UniformMaterialManagementSystem.ViewModels
 
                     firstNullRowIndex = firstNullRowIndex < rowIndex ? firstNullRowIndex : rowIndex;
                 }
-                MessageBox.Show($"以下未填项为必录项,不允许保存:" + nullMsg.ToString());
+                MessageBox.Show($"以下未填项为必录项,不允许保存:" + nullMsg.ToString(), "错误", MessageBoxButton.OK, MessageBoxImage.Error);
 
                 // 定位到第一行没填必录项的行
                 int firstNullColIndex = nullIndexes[firstNullRowIndex];
@@ -206,6 +207,27 @@ namespace UniformMaterialManagementSystem.ViewModels
                 return;
             }
 
+            // 检查新增行的代码是否符合规范
+            Regex regex = new Regex(@"^[0-9a-zA-Z]{1,2}$");
+            var illegalCodeCompanies = Companies.Where(x => x.IsNewRow && !regex.IsMatch(x.Code));
+            if (illegalCodeCompanies.Any())
+            {
+                StringBuilder illegalCodeMsg = new StringBuilder();
+                int firstIllegalRowIndex = Companies.Count;
+                foreach (var illegalCompany in illegalCodeCompanies)
+                {
+                    int rowIndex = Companies.IndexOf(illegalCompany);
+                    illegalCodeMsg.Append($"\n第 {rowIndex} 行的代码 '{illegalCompany.Code}'");
+
+                    firstIllegalRowIndex = firstIllegalRowIndex < rowIndex ? firstIllegalRowIndex : rowIndex;
+                }
+                MessageBox.Show($"材料代码只允许2位数字或字母,以下代码不合法,请修改后再次保存:" + illegalCodeMsg.ToString(), "错误", MessageBoxButton.OK, MessageBoxImage.Error);
+
+                // 定位到第一个非法的材料代码
+                SetCellEditing(dataGridMC, firstIllegalRowIndex, 2);
+                return;
+            }
+
             // 保存时检查前三列是否存在重复项
             var repeatNames = Companies.GroupBy(x => x.Name).Where(g => g.Count() > 1).Select(g => g.Key);
             var repeatShortNames = Companies.GroupBy(x => x.ShortName).Where(g => g.Count() > 1).Select(g => g.Key);
@@ -292,7 +314,7 @@ namespace UniformMaterialManagementSystem.ViewModels
             // 若存在重复项则提示后返回
             if (repeatMsg.Length > 0)
             {
-                MessageBox.Show("材料企业名称、材料企业简称、材料企业代码、军网材料企业代码列不允许重复,请修改后保存:" + repeatMsg.ToString());
+                MessageBox.Show("材料企业名称、材料企业简称、材料企业代码、军网材料企业代码列不允许重复,请修改后保存:" + repeatMsg.ToString(), "错误", MessageBoxButton.OK, MessageBoxImage.Error);
 
                 // 定位到第一个重复项
                 int repeatColIndex = repeatIndexes[firstRepeatRowIndex];

+ 234 - 149
UniformMaterialManagementSystem/ViewModels/MaterialViewModel.cs

@@ -2,6 +2,7 @@
 using System.Collections;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
+using System.Data;
 using System.IO;
 using System.Linq;
 using System.Security.Cryptography.X509Certificates;
@@ -15,6 +16,8 @@ using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using CommunityToolkit.Mvvm.ComponentModel;
 using CommunityToolkit.Mvvm.Input;
+using DocumentFormat.OpenXml;
+using DocumentFormat.OpenXml.Packaging;
 using DocumentFormat.OpenXml.Spreadsheet;
 using DocumentFormat.OpenXml.Wordprocessing;
 using Microsoft.EntityFrameworkCore;
@@ -30,14 +33,7 @@ namespace UniformMaterialManagementSystem.ViewModels
     {
         // 数据源
         [ObservableProperty]
-        private ObservableCollection<MaterialModel> _materials = new ObservableCollection<MaterialModel>();
-
-        [ObservableProperty]
-        private bool _btnUploadEnabled = false;
-
-        // 材料图片
-        [ObservableProperty]
-        private BitmapImage _materialPhoto = new BitmapImage();
+        private ObservableCollection<Material> _materials = new ObservableCollection<Material>();
 
         private IDataBaseService<Material>? _service;
 
@@ -54,52 +50,27 @@ namespace UniformMaterialManagementSystem.ViewModels
         }
 
         [RelayCommand]
-        private void SelectedCellsChanged(object parameters)
+        private void SelectedCellsChanged(DataGrid dataGridMaterial)
         {
-            // 命令绑定多个参数
-            var values = (object[])parameters;
-            DataGrid dataGridMaterial = (DataGrid)values[0];
-            Image img = (Image)values[1];
-            if (dataGridMaterial == null || img == null) { return; }
-
             // 获取当前行
             var cells = dataGridMaterial.SelectedCells;
             if (cells.Count == 0) { return; }
-            MaterialModel? currMaterial = cells[0].Item as MaterialModel;
+            Material? currMaterial = cells[0].Item as Material;
             if (currMaterial == null) { return; }
 
-            // 只有新增行可编辑:DataGrid 可编辑,上传图片按钮可用
-            if (currMaterial.IsNewRow)
+            foreach (DataGridColumn col in dataGridMaterial.Columns)
             {
-                dataGridMaterial.IsReadOnly = false;
-                BtnUploadEnabled = true;
-                dataGridMaterial.BeginEdit();
-            }
-            else
-            {
-                dataGridMaterial.IsReadOnly = true;
-                BtnUploadEnabled = false;
-            }
-
-            // 如果本行没有上传图片,则清空图片控件
-            if (currMaterial.Photo == null)
-            {
-                img.Source = null;
-                return;
-            }
-
-            // 将 Photo 数据展示到界面上
-            using (Stream stream = new MemoryStream(currMaterial.Photo))
-            {
-                BitmapImage bitmapImage = new BitmapImage();
-                stream.Position = 0;
-                bitmapImage.BeginInit();
-                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
-                bitmapImage.StreamSource = stream;
-                bitmapImage.EndInit();
-                bitmapImage.Freeze();
-
-                img.Source = bitmapImage;
+                // 新增行 和 已保存行的“材料规范名称”列可编辑
+                if (currMaterial.IsNewRow || col.Header.Equals("材料规范名称"))
+                {
+                    col.IsReadOnly = false;
+                    dataGridMaterial.BeginEdit(); // 单击进入编辑状态
+                }
+                // 已保存行的其他列只读
+                else
+                {
+                    col.IsReadOnly = true;
+                }
             }
         }
 
@@ -107,12 +78,11 @@ namespace UniformMaterialManagementSystem.ViewModels
         private void Append(DataGrid dataGridMaterial)
         {
             // 新增
-            //Material newMaterial = new Material();
-            MaterialModel newMaterialModel = new MaterialModel(new Material(), true, "");
-            Materials.Add(newMaterialModel);
+            Material newMaterial = new Material();
+            Materials.Add(newMaterial);
 
             // 定位到新增行
-            int index = Materials.IndexOf(newMaterialModel);
+            int index = Materials.IndexOf(newMaterial);
             SetCellEditing(dataGridMaterial, index, 0);
         }
 
@@ -128,7 +98,7 @@ namespace UniformMaterialManagementSystem.ViewModels
                 return;
             }
 
-            MaterialModel? currMaterial = cells[0].Item as MaterialModel;
+            Material? currMaterial = cells[0].Item as Material;
             if (currMaterial == null) { return; }
 
             // 新增行直接删除
@@ -146,40 +116,22 @@ namespace UniformMaterialManagementSystem.ViewModels
             }
 
             currMaterial.IsEnabled = false;
-            Material? material = _service?.Get(currMaterial.Guid);
-            if (material == null) { return; }
-            material.IsEnabled = false;
-            // 界面删除
-            //Materials.Remove(currMaterial);
 
             // 数据库保存
-            _service?.Update(material);
+            _service?.Update(currMaterial);
             _service?.SaveChanges();
             LoadData();
         }
 
         [RelayCommand]
-        private void Save(object parameters)
+        private void Save(DataGrid dataGridMaterial)
         {
-            // 命令绑定多个参数
-            var values = (object[])parameters;
-            DataGrid dataGridMaterial = (DataGrid)values[0];
-            Image img = (Image)values[1];
-            if (dataGridMaterial == null || img == null) { return; }
-
             // 编辑后的单元格没有提交成功:列绑定设置(DataGrid 注册 CellEditEnding 没用)
             bool commit = dataGridMaterial.CommitEdit();
             dataGridMaterial.UnselectAllCells();
 
             // 删除空行
-            var emptyRows = Materials.Where(x => x.IsNewRow && string.IsNullOrEmpty(x.Name) && string.IsNullOrEmpty(x.VarietyCode) && string.IsNullOrEmpty(x.CategoryCode) && string.IsNullOrEmpty(x.Specification) && string.IsNullOrEmpty(x.MeasureUnit) && string.IsNullOrEmpty(x.NormName) && x.Photo == null && string.IsNullOrEmpty(x.ShortName) && string.IsNullOrEmpty(x.Note));
-            if (emptyRows.Any())
-            {
-                for (int i = emptyRows.Count() - 1; i >= 0; i--)
-                {
-                    Materials.Remove(emptyRows.ElementAt(i));
-                }
-            }
+            DeleteEmptyRows();
 
             // 检查新增行的必录项是否为空
             var nullMaterials = Materials.Where(x => x.IsNewRow && (string.IsNullOrEmpty(x.Name) || string.IsNullOrEmpty(x.VarietyCode) || string.IsNullOrEmpty(x.CategoryCode) || string.IsNullOrEmpty(x.Specification) || string.IsNullOrEmpty(x.MeasureUnit)));
@@ -189,13 +141,13 @@ namespace UniformMaterialManagementSystem.ViewModels
                 Dictionary<int, int> nullIndexes = new Dictionary<int, int>();
                 StringBuilder nullMsg = new StringBuilder();
                 int firstNullRowIndex = Materials.Count;
-                foreach (MaterialModel nullItem in nullMaterials)
+                foreach (Material nullItem in nullMaterials)
                 {
                     int rowIndex = Materials.IndexOf(nullItem);
-                    int nullColIndex = string.IsNullOrEmpty(nullItem.Name) ? 0 
+                    int nullColIndex = string.IsNullOrEmpty(nullItem.Name) ? 0
                                        : string.IsNullOrEmpty(nullItem.VarietyCode) ? 1
                                        : string.IsNullOrEmpty(nullItem.CategoryCode) ? 2
-                                       : string.IsNullOrEmpty(nullItem.Specification) ? 3 
+                                       : string.IsNullOrEmpty(nullItem.Specification) ? 3
                                        : 4;
                     nullIndexes.Add(rowIndex, nullColIndex);
 
@@ -219,7 +171,7 @@ namespace UniformMaterialManagementSystem.ViewModels
                 return;
             }
 
-            // 保存时检查材料名称、材料简称是否存在重复项
+            // 保存时检查材料名称是否存在重复项
             var repeatNames = Materials.GroupBy(x => x.Name).Where(g => g.Count() > 1).Select(g => g.Key);
             StringBuilder repeatMsg = new StringBuilder();
             Dictionary<int, int> repeatIndexes = new Dictionary<int, int>();
@@ -230,7 +182,7 @@ namespace UniformMaterialManagementSystem.ViewModels
                 repeatMsg.Append($"\n材料名称列存在重复值[{repeatNameText}]");
 
                 // 记录重复项的索引
-                MaterialModel? repeatNameRow = Materials.Where(x => x.IsNewRow && repeatNames.Contains(x.Name)).FirstOrDefault();
+                Material? repeatNameRow = Materials.Where(x => x.IsNewRow && repeatNames.Contains(x.Name)).FirstOrDefault();
                 if (repeatNameRow == null) { return; }
                 int rowIndex = Materials.IndexOf(repeatNameRow);
                 if (!repeatIndexes.ContainsKey(rowIndex))
@@ -261,21 +213,7 @@ namespace UniformMaterialManagementSystem.ViewModels
 
                 // 插入一行
                 item.IsNewRow = false;
-                Material? material = new Material()
-                {
-                    Guid = item.Guid,
-                    Name = item.Name,
-                    VarietyCode = item.VarietyCode,
-                    CategoryCode = item.CategoryCode,
-                    Specification = item.Specification,
-                    MeasureUnit = item.MeasureUnit,
-                    NormName = item.NormName,
-                    Photo = item.Photo,
-                    Note = item.Note,
-                    ShortName = item.ShortName,
-                    IsEnabled = item.IsEnabled,
-                };
-                _service?.Insert(material);
+                _service?.Insert(item);
                 changedCount++;
             }
 
@@ -295,68 +233,150 @@ namespace UniformMaterialManagementSystem.ViewModels
         }
 
         [RelayCommand]
-        private void PanelClick(object parameters)
+        private void Import(DataGrid dataGridMaterial)
         {
-            // 命令绑定多个参数
-            var values = (object[])parameters;
-            DataGrid dataGridMaterial = (DataGrid)values[0];
-            Image img = (Image)values[1];
-            if (dataGridMaterial == null || img == null) { return; }
+            // 自动清除新增的空行
+            DeleteEmptyRows();
 
-            // 必须选择一行
-            var cells = dataGridMaterial.SelectedCells;
-            if (cells == null || cells.Count == 0)
+            // 若存在未保存的行,则不允许导入
+            var newRows = Materials.Where(x => x.IsNewRow);
+            if (newRows.Any())
             {
-                MessageBox.Show("请选择一行后再上传图片", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
+                MessageBox.Show("存在未保存的行,请保存后导入。");
                 return;
             }
 
-            // 新增行 或 没上传图片的已保存行可以上传图片
-            var currItem = cells[0].Item as MaterialModel;
-            if (currItem == null) { return; }
-
-            // 新增行未保存前可以一直换图片,已保存行点击图片后就不能修改了
-            if (!currItem.IsNewRow) { return; }
-
-            // 打开文件选择对话框
+            // 选择导入的文件
             OpenFileDialog openFileDialog = new OpenFileDialog();
-            openFileDialog.Filter = "图像文件|*.jpg;*.png;*.jpeg;*.bmp;*.gif|所有文件|*.*";
-            openFileDialog.InitialDirectory = @"D:\Users\Administrator\Desktop"; //文件选择的默认路径
+            openFileDialog.Title = "选择导入文件的路径";
+            openFileDialog.Filter = "Excel 文件|*.xlsx;*.xls|Excel 工作簿|*.xlsx|Excel 97-2003工作簿|*.xls"; // 只能导入Excel
+            string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
+            openFileDialog.InitialDirectory = desktopPath; // 默认从桌面获取文件
             if (openFileDialog.ShowDialog() != true) { return; }
 
-            // 获取选择的图片
-            string fileName = openFileDialog.FileName;
-            BitmapImage bitmapImage = new BitmapImage(new Uri(fileName));
-            img.Source = bitmapImage;
-
-            // 行切换时保存图片
-            byte[] imgContent = File.ReadAllBytes(fileName);
-            // 方法二:
-            //Stream ms;
-            //byte[] imgContent;
-            //if ((ms = openFileDialog.OpenFile()) != null)
-            //{
-            //    // 读取文件的二进制数据
-            //    imgContent = new byte[ms.Length];
-            //    ms.Position = 0;
-            //    ms.Read(imgContent, 0, Convert.ToInt32(ms.Length));
-            //}
-
-            currItem.Photo = imgContent;
-            currItem.UploadSign = RegularFontUtil.Checkmark_Circle_32;
-
-            // 已上传图片显示标志
-            //TextBlock? tb = dataGridMaterial.Columns[4].GetCellContent(currItem) as TextBlock;
-            //if (tb != null)
-            //{
-            //    tb.Text = RegularFontUtil.Checkmark_Circle_32;
-            //}
+            // 导入 Excel
+            // todo OpenXml 读取时会自动跳过空白单元格(因为Excel的xml只存储有数据的单元格的内容),所以当行存在空白单元格时,会自动左移
+            DataTable dtImport0 = ExcelUtil.ReadExcelFileToDataTable(openFileDialog.FileName);
+            DataTable? dtImport = OpenXmlExcelUtil.ExcelToDataTable(openFileDialog.FileName);
+            if(dtImport == null || dtImport.Rows.Count == 0)
+            {
+                MessageBox.Show("获取Excel数据失败,请重试!");
+                return;
+            }
+
+            // 检查 Excel 中是否存在重复项
+            StringBuilder checkExcelMsg = new StringBuilder();
+            var importRepeatGuid = dtImport.AsEnumerable().GroupBy(x => x["内码"]).Where(g => g.Count() > 1).Select(g => g.Key).ToList();
+            var importRepeatNames = dtImport.AsEnumerable().GroupBy(x => x["材料名称*"]).Where(g => g.Count() > 1).Select(g => g.Key).ToList();
+            if (importRepeatGuid.Any())
+            {
+                string guids = string.Join("、", importRepeatGuid);
+                checkExcelMsg.AppendLine($"内码:[{guids}]");
+            }
+            if (importRepeatNames.Any())
+            {
+                string names = string.Join("、", importRepeatNames);
+                checkExcelMsg.AppendLine($"材料名称:[{names}]");
+            }
+            if (checkExcelMsg.Length > 0)
+            {
+                MessageBox.Show("Excel 中存在以下重复数据,请检查数据后重新导入:\n" + checkExcelMsg.ToString(), "错误", MessageBoxButton.OK, MessageBoxImage.Error);
+                return;
+            }
+
+            // 导入 Excel 中的数据
+            string[] mateGuids = Materials.Select(x => x.Guid.ToString()).ToArray();
+            string[] mateNames = Materials.Select(x => x.Name).ToArray();
+            StringBuilder importRepeatMsg = new StringBuilder();
+            StringBuilder importNullMsg = new StringBuilder();
+            int importCount = 0;
+            foreach (DataRow dr in dtImport.Rows)
+            {
+                // 跳过系统中已存在的行:直接跳过,不提示
+                if (mateGuids.Contains(dr["内码"].ToString())) { continue; }
+
+                // 跳过系统中已经存在的材料名称:提示用户 Excel 中哪几行的材料名称已存在,不导入
+                if (mateNames.Contains(dr["材料名称*"].ToString()))
+                {
+                    // 拼接重复的材料名称
+                    importRepeatMsg.Append($"\n第 {dtImport.Rows.IndexOf(dr) + 1} 行的 “{dr["材料名称*"]}”");
+                    continue;
+                }
+
+                // 跳过必录项为空的行:提示用户 Excel 中哪几行的必录项为空,检查数据后重新导入
+                if (string.IsNullOrWhiteSpace(dr["内码"].ToString()) || string.IsNullOrWhiteSpace(dr["材料名称*"].ToString()) || string.IsNullOrWhiteSpace(dr["品种代码*"].ToString()) || string.IsNullOrWhiteSpace(dr["材料类型代码*"].ToString()) || string.IsNullOrWhiteSpace(dr["材料规格*"].ToString()) || string.IsNullOrWhiteSpace(dr["计量单位*"].ToString()))
+                {
+                    // 拼接行号
+                    importNullMsg.Append($"第 [{dtImport.Rows.IndexOf(dr) + 1}] 行、");
+                    continue;
+                }
+
+                // 从 DataRow → Material
+                Material material = ConvertToEntity(dr);
+                Materials.Add(material);
+                _service?.Insert(material);
+                importCount++;
+            }
+
+            // 拼接导入异常信息
+            if (importRepeatMsg.Length > 0)
+            {
+                importRepeatMsg = importRepeatMsg.Remove(importRepeatMsg.Length - 1, 1);
+                importRepeatMsg = importRepeatMsg.Insert(0, $"忽略材料名称已存在的行:").AppendLine();
+            }
+            if (importNullMsg.Length > 0)
+            {
+                importNullMsg = importNullMsg.Remove(importNullMsg.Length - 1, 1);
+                importNullMsg = importNullMsg.Insert(0, "忽略存在为空的必录项的行:").AppendLine();
+            }
+            
+
+            if (importCount > 0)
+            {
+                bool? isSuccess = _service?.SaveChanges();
+                if (isSuccess == true)
+                {
+                    MessageBox.Show($"成功导入 {importCount} 行。\n" + importRepeatMsg + importNullMsg);
+                }
+                else
+                {
+                    MessageBox.Show($"导入失败!\n" + importRepeatMsg + importNullMsg);
+                }
+            }
+            else
+            {
+                MessageBox.Show($"选择的文件中没有需要导入的行!\n" + importRepeatMsg + importNullMsg);
+            }
         }
 
         [RelayCommand]
-        private void PhotoClickCommand()
+        private void Export(DataGrid dataGridMaterial)
         {
+            // 自动清除新增的空行
+            DeleteEmptyRows();
+
+            // 若存在未保存的行,则不允许导出
+            var newRows = Materials.Where(x => x.IsNewRow);
+            if (newRows.Any())
+            {
+                MessageBox.Show("存在未保存的行,请保存后导出。");
+                return;
+            }
 
+            // 选择导出路径
+            SaveFileDialog saveFileDialog = new SaveFileDialog();
+            saveFileDialog.Title = "选择保存文件的路径";
+            saveFileDialog.Filter = "Excel 文件|*.xlsx;*.xls|Excel 工作簿|*.xlsx|Excel 97-2003工作簿|*.xls|所有文件|*.*";
+            string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
+            saveFileDialog.InitialDirectory = desktopPath; // 默认保存到桌面。若不设置,默认保存到 文档 路径下
+            string fileName = "材料目录-" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xlsx";
+            saveFileDialog.FileName = fileName; // 默认文件名
+            if (saveFileDialog.ShowDialog() != true) { return; }
+
+            // 导出 Excel
+            DataTable dtMate = CreateDataTable();
+            ExcelUtil.CreateExcelFromDataTable(dtMate, saveFileDialog.FileName);
+            // todo 列宽自适应,文本格式?标题行加粗?
         }
 
         /// <summary>
@@ -374,16 +394,25 @@ namespace UniformMaterialManagementSystem.ViewModels
             Materials.Clear();
             foreach (var mate in materials)
             {
-                // 已上传图片的行显示标记
-                string uploadSign = mate.Photo == null ? string.Empty : RegularFontUtil.Checkmark_Circle_32;
-                MaterialModel materialModel = new MaterialModel(mate, false, uploadSign);
-
-                Materials.Add(materialModel);
+                mate.IsNewRow = false;// 已保存的行 IsNewRow 为 false
+                Materials.Add(mate);
             }
+        }
 
-            // todo 先增加字段,图片暂时先隐藏,不删除数据库数据(用户的 CompanyName 字段也一起删除)
-            // todo 刷新后把图片数据重置
-            // todo 刚进入时也清空图片
+        /// <summary>
+        /// 删除新增的空行
+        /// </summary>
+        private void DeleteEmptyRows()
+        {
+            // 删除新增的空行
+            var emptyRows = Materials.Where(x => x.IsNewRow && string.IsNullOrEmpty(x.Name) && string.IsNullOrEmpty(x.VarietyCode) && string.IsNullOrEmpty(x.CategoryCode) && string.IsNullOrEmpty(x.Specification) && string.IsNullOrEmpty(x.MeasureUnit) && string.IsNullOrEmpty(x.NormName) && string.IsNullOrEmpty(x.Note));
+            if (emptyRows.Any())
+            {
+                for (int i = emptyRows.Count() - 1; i >= 0; i--)
+                {
+                    Materials.Remove(emptyRows.ElementAt(i));
+                }
+            }
         }
 
         /// <summary>
@@ -443,5 +472,61 @@ namespace UniformMaterialManagementSystem.ViewModels
             cell.IsSelected = true;
             dataGrid.BeginEdit();
         }
+
+        /// <summary>
+        /// 界面数据转换为 DataTable
+        /// </summary>
+        /// <returns></returns>
+        private DataTable CreateDataTable()
+        {
+            // 创建 DataTable 
+            DataTable dtMate = new DataTable();
+            dtMate.Columns.Add("内码", typeof(string));
+            dtMate.Columns.Add("材料名称*", typeof(string));
+            dtMate.Columns.Add("品种代码*", typeof(string));
+            dtMate.Columns.Add("材料类型代码*", typeof(string));
+            dtMate.Columns.Add("材料规格*", typeof(string));
+            dtMate.Columns.Add("计量单位*", typeof(string));
+            dtMate.Columns.Add("材料规范名称", typeof(string));
+            dtMate.Columns.Add("备注", typeof(string));
+            dtMate.Columns.Add("是否可用", typeof(string));
+
+            // 添加数据
+            foreach (var mate in Materials)
+            {
+                DataRow dr = dtMate.NewRow();
+                dr["内码"] = mate.Guid;
+                dr["材料名称*"] = mate.Name;
+                dr["品种代码*"] = mate.VarietyCode;
+                dr["材料类型代码*"] = mate.CategoryCode;
+                dr["材料规格*"] = mate.Specification;
+                dr["计量单位*"] = mate.MeasureUnit;
+                dr["材料规范名称"] = mate.NormName;
+                dr["备注"] = mate.Note;
+                dr["是否可用"] = mate.IsEnabled ? "是" : "否";
+                dtMate.Rows.Add(dr);
+            }
+
+            return dtMate;
+        }
+
+
+        private Material ConvertToEntity(DataRow dr)
+        {
+            Material material = new Material();
+            material.Guid = Guid.Parse(dr["内码"].ToString() ?? "");
+            if (dr == null) { return null; }
+            material.Name = dr["材料名称*"].ToString() ?? "";
+            material.VarietyCode = dr["品种代码*"].ToString() ?? "";
+            material.CategoryCode = dr["材料类型代码*"].ToString() ?? "";
+            material.Specification = dr["材料规格*"].ToString() ?? "";
+            material.MeasureUnit = dr["计量单位*"].ToString() ?? "";
+            material.NormName = dr["材料规范名称"].ToString() ?? "";
+            material.Note = dr["备注"].ToString();
+            material.IsEnabled = dr["是否可用"].ToString()!.Equals("是") ? true : false;
+            material.IsNewRow = false;  // 直接保存
+
+            return material;
+        }
     }
 }

+ 4 - 3
UniformMaterialManagementSystem/ViewModels/UsersViewModel.cs

@@ -96,9 +96,10 @@ namespace UniformMaterialManagementSystem.ViewModels
         private void Loaded(DataGrid dataGridUser)
         {
             // 加载时设置列标题、可读性
-            DataGridTextColumn? colIdNumber = dataGridUser.Columns[0] as DataGridTextColumn;
-            DataGridComboBoxColumn? colSupUnit = dataGridUser.Columns[3] as DataGridComboBoxColumn;
-            DataGridComboBoxColumn? colCompany = dataGridUser.Columns[4] as DataGridComboBoxColumn;
+            
+            DataGridTextColumn? colIdNumber = dataGridUser.Columns.Where(x => x.Header.ToString()!.StartsWith("工号")).FirstOrDefault() as DataGridTextColumn;
+            DataGridComboBoxColumn? colSupUnit = dataGridUser.Columns.Where(x => x.Header.ToString()!.StartsWith("监管单位")).FirstOrDefault() as DataGridComboBoxColumn;
+            DataGridComboBoxColumn? colCompany = dataGridUser.Columns.Where(x => x.Header.ToString()!.StartsWith("生产企业")).FirstOrDefault() as DataGridComboBoxColumn;
             if (colIdNumber == null || colSupUnit == null || colCompany == null) { return; }
 
             var adminOrSupUnitRoles = _currUser.Roles.Where(x => x.Name.Equals("Admin") || x.Name.Contains("Supervision"));

+ 5 - 5
UniformMaterialManagementSystem/Views/DeliveryReceiptControl.xaml

@@ -316,20 +316,20 @@
 
                 <!-- 数据结构 -->
                 <DataGrid.Columns>
-                    <DataGridTextColumn Header="采购机构" Width="2*"
+                    <DataGridTextColumn Header="采购机构" Width="200"
                                         ElementStyle="{StaticResource TextColumnElementStyle}"
                                         Binding="{Binding PurchaseCompany}" />
-                    <DataGridTextColumn Header="合同编号" Width="*"
+                    <DataGridTextColumn Header="合同编号" Width="100"
                                         ElementStyle="{StaticResource TextColumnElementStyle}"
                                         Binding="{Binding ContractNo}" />
                     <!-- todo 字段是 string 类型的? -->
-                    <DataGridTextColumn Header="合同签订时间" Width="*"
+                    <DataGridTextColumn Header="合同签订时间" Width="100"
                                         ElementStyle="{StaticResource TextColumnElementStyle}"
                                         Binding="{Binding SigningDate, StringFormat='yyyy/MM/dd'}" />
-                    <DataGridTextColumn Header="合同数量" Width="*"
+                    <DataGridTextColumn Header="合同数量" Width="100"
                                         ElementStyle="{StaticResource TextColumnElementStyle}"
                                         Binding="{Binding InspectQty}" />
-                    <DataGridTextColumn Header="可报检数量" Width="*"
+                    <DataGridTextColumn Header="可报检数量" Width="100"
                                         ElementStyle="{StaticResource TextColumnElementStyle}"
                                         Binding="{Binding UnInspectQty}" />
                 </DataGrid.Columns>

+ 0 - 1
UniformMaterialManagementSystem/Views/MaterialCompany.xaml

@@ -202,7 +202,6 @@
                   Background="White"
                   AutoGenerateColumns="False"
                   CanUserAddRows="False"
-                  CanUserReorderColumns="False"
                   SelectionMode="Single"
                   SelectionUnit="CellOrRowHeader"
                   ItemsSource="{Binding Companies, Mode=TwoWay}"

+ 24 - 137
UniformMaterialManagementSystem/Views/MaterialControl.xaml

@@ -162,7 +162,6 @@
     <Grid>
         <!-- 定义页面布局 -->
         <Grid.ColumnDefinitions>
-            <ColumnDefinition Width="3*"/>
             <ColumnDefinition Width="*"/>
         </Grid.ColumnDefinitions>
         <Grid.RowDefinitions>
@@ -179,33 +178,37 @@
                 <ToolBar Background="White"
                          ToolBarTray.IsLocked="True">
                     <Button x:Name="tsBtnAppend"
-                            HorizontalContentAlignment="Center"
-                            Command="{Binding AppendCommand}"
-                            CommandParameter="{Binding ElementName=dataGridMaterial}"
                             Content="新增"
                             Tag="{x:Static utils:RegularFontUtil.Add_Circle_32}"
-                            Template="{StaticResource CustomToolBarButtomTemplate}" />
+                            Template="{StaticResource CustomToolBarButtomTemplate}"
+                            Command="{Binding AppendCommand}"
+                            CommandParameter="{Binding ElementName=dataGridMaterial}" />
                     <Button x:Name="tsBtnDelete"
-                            HorizontalContentAlignment="Center"
-                            Command="{Binding DeleteCommand}"
-                            CommandParameter="{Binding ElementName=dataGridMaterial}"
                             Content="删除"
                             Tag="{x:Static utils:RegularFontUtil.Delete_32}"
-                            Template="{StaticResource CustomToolBarButtomTemplate}" />
+                            Template="{StaticResource CustomToolBarButtomTemplate}" 
+                            Command="{Binding DeleteCommand}"
+                            CommandParameter="{Binding ElementName=dataGridMaterial}" />
                     <Separator />
                     <Button x:Name="tsBtnSave"
-                            HorizontalContentAlignment="Center"
-                            Command="{Binding SaveCommand}"
                             Content="保存"
                             Tag="{x:Static utils:RegularFontUtil.Save_32}"
-                            Template="{StaticResource CustomToolBarButtomTemplate}">
-                        <Button.CommandParameter>
-                            <MultiBinding Converter="{StaticResource MultiParamConverter}">
-                                <Binding ElementName="dataGridMaterial" />
-                                <Binding ElementName="imgPhoto" />
-                            </MultiBinding>
-                        </Button.CommandParameter>
-                    </Button>
+                            Template="{StaticResource CustomToolBarButtomTemplate}" 
+                            Command="{Binding SaveCommand}"
+                            CommandParameter="{Binding ElementName=dataGridMaterial}"/>
+                    <Separator />
+                    <Button x:Name="tsBtnImprot"
+                            Content="导入"
+                            Tag="{x:Static utils:RegularFontUtil.Share_Close_Tray_24}"
+                            Template="{StaticResource CustomToolBarButtomTemplate}" 
+                            Command="{Binding ImportCommand}"
+                            CommandParameter="{Binding ElementName=dataGridMaterial}" />
+                    <Button x:Name="tsBtnExprot"
+                            Content="导出"
+                            Tag="{x:Static utils:RegularFontUtil.Share_Screen_Start_24}"
+                            Template="{StaticResource CustomToolBarButtomTemplate}" 
+                            Command="{Binding ExportCommand}"
+                            CommandParameter="{Binding ElementName=dataGridMaterial}" />
                 </ToolBar>
             </ToolBarPanel>
         </Border>
@@ -248,14 +251,8 @@
             <behaviors:Interaction.Triggers>
                 <!-- 单元格切换事件 -->
                 <behaviors:EventTrigger EventName="SelectedCellsChanged">
-                    <behaviors:InvokeCommandAction Command="{Binding SelectedCellsChangedCommand}">
-                        <behaviors:InvokeCommandAction.CommandParameter>
-                            <MultiBinding Converter="{StaticResource MultiParamConverter}">
-                                <Binding ElementName="dataGridMaterial" />
-                                <Binding ElementName="imgPhoto" />
-                            </MultiBinding>
-                        </behaviors:InvokeCommandAction.CommandParameter>
-                    </behaviors:InvokeCommandAction>
+                    <behaviors:InvokeCommandAction Command="{Binding SelectedCellsChangedCommand}"
+                                                   CommandParameter="{Binding ElementName=dataGridMaterial}" />
                 </behaviors:EventTrigger>
             </behaviors:Interaction.Triggers>
 
@@ -289,120 +286,10 @@
                                     Binding="{Binding Note, UpdateSourceTrigger = PropertyChanged}"
                                     EditingElementStyle="{StaticResource TextColumnEditingElementStyle}"
                                     ElementStyle="{StaticResource TextColumnElementStyle}" />
-                <DataGridTextColumn Header="×材料简称" Width="*" 
-                                    Binding="{Binding ShortName, UpdateSourceTrigger=PropertyChanged}"
-                                    EditingElementStyle="{StaticResource TextColumnEditingElementStyle}"
-                                    ElementStyle="{StaticResource TextColumnElementStyle}" />
-                <DataGridTextColumn Header="×上传标记" Width="50" 
-                                    FontFamily="{StaticResource FluentSystemIconsRegular}" 
-                                    Binding="{Binding UploadSign, UpdateSourceTrigger=PropertyChanged}"
-                                    ElementStyle="{StaticResource TextColumnElementStyle}"/>
                 
             </DataGrid.Columns>
         </DataGrid>
 
-        <!-- 图片控件:如果需要左右拖动图片容器,改用 GridSplitter -->
-        <Border x:Name="borderPhoto"
-                Grid.Row="1"
-                Grid.Column="1"
-                BorderThickness="1"
-                BorderBrush="Gray"
-                Background="White">
-            <DockPanel>
-                <!-- 按钮 -->
-                <Border  DockPanel.Dock="Top"
-                         CornerRadius="5">
-                    <Button HorizontalAlignment="Stretch"
-                            VerticalAlignment="Center"
-                            Background="White"
-                            Content="上传图片"
-                            FontWeight="Bold"
-                            Height="40"
-                            IsEnabled="{Binding Path=DataContext.BtnUploadEnabled,RelativeSource={RelativeSource AncestorType=UserControl}}"
-                            Command="{Binding PanelClickCommand}">
-
-                        <Button.CommandParameter>
-                            <MultiBinding Converter="{StaticResource MultiParamConverter }">
-                                <Binding ElementName="dataGridMaterial" />
-                                <Binding ElementName="imgPhoto" />
-                            </MultiBinding>
-                        </Button.CommandParameter>
-                        
-                        <!-- todo 暂时不改,先用默认的样式 -->
-                        <!--  Button默认模板中 IsMouseOver 属性有他自己的样式。 要想修改默认样式只能修改Button 内容模板 -->
-                        <!--<Button.Style>
-                            <Style TargetType="Button">
-                                <Style.Triggers>
-                                    <Trigger Property="IsMouseOver" Value="True">
-                                        <Setter Property="Template">
-                                            <Setter.Value>
-                                                <ControlTemplate>
-                                                    <Button Content="上传图片1"
-                                                               FontWeight="Bold"
-                                                               HorizontalAlignment="Center"
-                                                               VerticalAlignment="Center"
-                                                               Background="LightGray" />
-                                                </ControlTemplate>
-                                            </Setter.Value>
-                                        </Setter>
-                                    </Trigger>
-                                    <Trigger Property="IsMouseOver" Value="False">
-                                        <Setter Property="Template">
-                                            <Setter.Value>
-                                                <ControlTemplate>
-                                                    <Button Content="上传图片2"
-                                                               FontWeight="Bold"
-                                                               HorizontalAlignment="Center"
-                                                               VerticalAlignment="Center"
-                                                               Background="LightBlue" />
-                                                </ControlTemplate>
-                                            </Setter.Value>
-                                        </Setter>
-                                    </Trigger>
-                                </Style.Triggers>
-                            </Style>
-                        </Button.Style>-->
-                    </Button>
-                </Border>
-
-                <!-- 图片控件 -->
-                <Border BorderBrush="Gray"
-                        BorderThickness="1"
-                        DockPanel.Dock="Bottom"
-                        Background="White">
-                    <Viewbox Grid.Row="1"
-                             HorizontalAlignment="Stretch"
-                             VerticalAlignment="Center">
-                        <Image x:Name="imgPhoto" Margin="5" Stretch="Uniform" 
-                           HorizontalAlignment="Center"
-                           VerticalAlignment="Center"
-                           Source="{Binding MaterialPhoto}" >
-                            <!-- todo 后续有需要再说 -->
-                            <!--<Image.InputBindings>
-                        -->
-                            <!-- 不会触发 Border 的点击事件 -->
-                            <!--
-                        <MouseBinding MouseAction="LeftClick" Command="{Binding PhotoClickCommand}" />
-                    </Image.InputBindings>-->
-                        </Image>
-                    </Viewbox>
-
-                    <!-- 左键点击 -->
-                    <Border.InputBindings>
-                        <MouseBinding MouseAction="LeftClick" 
-                                      Command="{Binding PanelClickCommand}">
-                            <MouseBinding.CommandParameter>
-                                <MultiBinding Converter="{StaticResource MultiParamConverter }">
-                                    <Binding ElementName="dataGridMaterial" />
-                                    <Binding ElementName="imgPhoto" />
-                                </MultiBinding>
-                            </MouseBinding.CommandParameter>
-                        </MouseBinding>
-                    </Border.InputBindings>
-                </Border>
-            </DockPanel>
-        </Border>
-
     </Grid>
 
 </UserControl>

+ 1 - 1
UniformMaterialManagementSystem/Views/UsersControl.xaml

@@ -267,7 +267,7 @@
                                     ElementStyle="{StaticResource TextColumnElementStyle}" />
 
                 <!-- todo  TextBinding 属性 绑定 Entity.SupervisionUnit(SupervisionUnit类型) -->
-                <DataGridComboBoxColumn Header="监管单位*" Width="2*"
+                <DataGridComboBoxColumn Header="监管单位/所在单位*" Width="2*"
                                         DisplayMemberPath="Name"
                                         SelectedValuePath="Guid"
                                         TextBinding="{Binding SupervisionUnit.Name}">