liaoxujun@qq.com
2024-02-19 c32275f697e1541694836c47e1682e3291673dbc
完成系统设置页面,创建设置字典
7个文件已修改
25个文件已添加
1422 ■■■■■ 已修改文件
.gitignore 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz.DataAccess/DataContext.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz.Model/Set/Dictionary.cs 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz.Model/cy_scdz.Model.csproj 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz.Test/DictionaryControllerTest.cs 273 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz.Test/Properties/launchSettings.json 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz.ViewModel/Setting/SettingListVM.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz.ViewModel/Setting/SettingVm.cs 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz.ViewModel/cy_scdz.ViewModel.csproj 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz.ViewModel/dictionary/DictionaryVMs/DictionaryBatchVM.cs 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz.ViewModel/dictionary/DictionaryVMs/DictionaryImportVM.cs 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz.ViewModel/dictionary/DictionaryVMs/DictionaryListVM.cs 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz.ViewModel/dictionary/DictionaryVMs/DictionarySearcher.cs 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz.ViewModel/dictionary/DictionaryVMs/DictionaryVM.cs 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz.sln 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz/Areas/Setting/Controllers/SettingController.cs 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz/Areas/Setting/Views/Setting/index.cshtml 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz/Areas/dictionary/Controllers/DictionaryController.cs 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz/Areas/dictionary/Views/Dictionary/BatchDelete.cshtml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz/Areas/dictionary/Views/Dictionary/BatchEdit.cshtml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz/Areas/dictionary/Views/Dictionary/Create.cshtml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz/Areas/dictionary/Views/Dictionary/Delete.cshtml 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz/Areas/dictionary/Views/Dictionary/Details.cshtml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz/Areas/dictionary/Views/Dictionary/Edit.cshtml 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz/Areas/dictionary/Views/Dictionary/Import.cshtml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz/Areas/dictionary/Views/Dictionary/Index.cshtml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz/Views/Login/Login.cshtml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz/appsettings.json 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz/cy_scdz.csproj 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cy_scdz/cy_scdz.csproj.user 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/utils.csproj 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/utilsFun.cs 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
New file
@@ -0,0 +1,13 @@
.vs/
cy_scdz.DataAccess/bin/
cy_scdz.DataAccess/obj/
cy_scdz.Model/bin/
cy_scdz.Model/obj/
cy_scdz.Test/obj/
cy_scdz.ViewModel/bin/
cy_scdz.ViewModel/obj/
cy_scdz/bin/
cy_scdz/obj/Debug/
utils/obj/
cy_scdz/obj/
utils/bin/
cy_scdz.DataAccess/DataContext.cs
@@ -10,6 +10,7 @@
using WalkingTec.Mvvm.Core.Extensions;
using WalkingTec.Mvvm.Core.Models;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using cy_scdz.Model.Set;
namespace cy_scdz.DataAccess
{
@@ -18,7 +19,7 @@
        public DbSet<FrameworkUser> FrameworkUsers { get; set; }
        public DbSet<FrameworkUserRole> FrameworkUserRoles { get; set; }
        public DbSet<FrameworkUserGroup> FrameworkUserGroups { get; set; }
        public DbSet<Dictionary> Dictionary { get; set; }
        public DataContext(CS cs)
             : base(cs)
        {
cy_scdz.Model/Set/Dictionary.cs
New file
@@ -0,0 +1,52 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WalkingTec.Mvvm.Core;
namespace cy_scdz.Model.Set
{
    [Display(Name = "设置字典")]
    public class Dictionary: TreePoco<Dictionary>
    {
        /// <summary>
        /// 名称
        /// </summary>
        [Display(Name = "名称")]
        [StringLength(50, ErrorMessage = "Validate.{0}stringmax{1}")]
        [Comment("名称")]
        [Required]
        public string Name { get; set; }
        /// <summary>
        /// 名称
        /// </summary>
        [Display(Name = "Key")]
        [Comment("Key")]
        [Required]
        public string Key { get; set; }
        /// <summary>
        /// 值
        /// </summary>
        [Display(Name = "值")]
        [StringLength(200, ErrorMessage = "Validate.{0}stringmax{1}")]
        [Comment("值")]
        public string Value { get; set; }
        /// <summary>
        /// 是否有效
        /// </summary>
        [Display(Name = "是否有效")]
        [Comment("是否有效")]
        public bool IsEn { get; set; }= true;
        /// <summary>
        /// 子节点
        /// </summary>
        public virtual ICollection<Dictionary> Children { get; set; } = new List<Dictionary>();
    }
}
cy_scdz.Model/cy_scdz.Model.csproj
@@ -9,6 +9,6 @@
  <ItemGroup>
    <PackageReference Include="WalkingTec.Mvvm.Core" Version="6.5.6" />
  </ItemGroup >
  </ItemGroup>
</Project>
cy_scdz.Test/DictionaryControllerTest.cs
New file
@@ -0,0 +1,273 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WalkingTec.Mvvm.Core;
using cy_scdz.Controllers;
using cy_scdz.ViewModel.dictionary.DictionaryVMs;
using cy_scdz.Model.Set;
using cy_scdz.DataAccess;
namespace cy_scdz.Test
{
    [TestClass]
    public class DictionaryControllerTest
    {
        private SetingController _controller;
        private string _seed;
        public DictionaryControllerTest()
        {
            _seed = Guid.NewGuid().ToString();
            _controller = MockController.CreateController<SetingController>(new DataContext(_seed, DBTypeEnum.Memory), "user");
        }
        [TestMethod]
        public void SearchTest()
        {
            PartialViewResult rv = (PartialViewResult)_controller.Index();
            Assert.IsInstanceOfType(rv.Model, typeof(IBasePagedListVM<TopBasePoco, BaseSearcher>));
            string rv2 = _controller.Search((rv.Model as DictionaryListVM).Searcher);
            Assert.IsTrue(rv2.Contains("\"Code\":200"));
        }
        [TestMethod]
        public void CreateTest()
        {
            PartialViewResult rv = (PartialViewResult)_controller.Create();
            Assert.IsInstanceOfType(rv.Model, typeof(DictionaryVM));
            DictionaryVM vm = rv.Model as DictionaryVM;
            Dictionary v = new Dictionary();
            v.Name = "b";
            v.Key = "xMrl9";
            v.Value = "EywYKwZjnxDmyQVwVYph9bYpAudrE9fseXiODivU84zBNHxqZv7ztyImrm4bTwJHFxtTfnJfwnwkWtP9LQeWCjwoO0sKPFEz3KD5Ni6QzJViWgOZjbDtvCCAOM3Md";
            v.IsEn = true;
            v.ParentId = AddDictionary();
            vm.Entity = v;
            _controller.Create(vm);
            using (var context = new DataContext(_seed, DBTypeEnum.Memory))
            {
                var data = context.Set<Dictionary>().Find(v.ID);
                Assert.AreEqual(data.Name, "b");
                Assert.AreEqual(data.Key, "xMrl9");
                Assert.AreEqual(data.Value, "EywYKwZjnxDmyQVwVYph9bYpAudrE9fseXiODivU84zBNHxqZv7ztyImrm4bTwJHFxtTfnJfwnwkWtP9LQeWCjwoO0sKPFEz3KD5Ni6QzJViWgOZjbDtvCCAOM3Md");
                Assert.AreEqual(data.IsEn, true);
            }
        }
        [TestMethod]
        public void EditTest()
        {
            Dictionary v = new Dictionary();
            using (var context = new DataContext(_seed, DBTypeEnum.Memory))
            {
                v.Name = "b";
                v.Key = "xMrl9";
                v.Value = "EywYKwZjnxDmyQVwVYph9bYpAudrE9fseXiODivU84zBNHxqZv7ztyImrm4bTwJHFxtTfnJfwnwkWtP9LQeWCjwoO0sKPFEz3KD5Ni6QzJViWgOZjbDtvCCAOM3Md";
                v.IsEn = true;
                v.ParentId = AddDictionary();
                context.Set<Dictionary>().Add(v);
                context.SaveChanges();
            }
            PartialViewResult rv = (PartialViewResult)_controller.Edit(v.ID.ToString());
            Assert.IsInstanceOfType(rv.Model, typeof(DictionaryVM));
            DictionaryVM vm = rv.Model as DictionaryVM;
            vm.Wtm.DC = new DataContext(_seed, DBTypeEnum.Memory);
            v = new Dictionary();
            v.ID = vm.Entity.ID;
            v.Name = "QsFRU0Hrpj0paqSATzzz7bBy7XUEiXX3n2ochswiODO";
            v.Key = "xpZrS27u53";
            v.Value = "guWhKhfl1PVouMDiYmcgkvledon5IsxDS1OmRCXsI7DN5NMIKex21a9FdhlIzkPnMebXpH5Lvb2kOk0ADso6eGecpBYjRnFQcZopebKAQp1q7XghV67Mbqe7Uy";
            v.IsEn = false;
            vm.Entity = v;
            vm.FC = new Dictionary<string, object>();
            vm.FC.Add("Entity.Name", "");
            vm.FC.Add("Entity.Key", "");
            vm.FC.Add("Entity.Value", "");
            vm.FC.Add("Entity.IsEn", "");
            vm.FC.Add("Entity.ParentId", "");
            _controller.Edit(vm);
            using (var context = new DataContext(_seed, DBTypeEnum.Memory))
            {
                var data = context.Set<Dictionary>().Find(v.ID);
                Assert.AreEqual(data.Name, "QsFRU0Hrpj0paqSATzzz7bBy7XUEiXX3n2ochswiODO");
                Assert.AreEqual(data.Key, "xpZrS27u53");
                Assert.AreEqual(data.Value, "guWhKhfl1PVouMDiYmcgkvledon5IsxDS1OmRCXsI7DN5NMIKex21a9FdhlIzkPnMebXpH5Lvb2kOk0ADso6eGecpBYjRnFQcZopebKAQp1q7XghV67Mbqe7Uy");
                Assert.AreEqual(data.IsEn, false);
            }
        }
        [TestMethod]
        public void DeleteTest()
        {
            Dictionary v = new Dictionary();
            using (var context = new DataContext(_seed, DBTypeEnum.Memory))
            {
                v.Name = "b";
                v.Key = "xMrl9";
                v.Value = "EywYKwZjnxDmyQVwVYph9bYpAudrE9fseXiODivU84zBNHxqZv7ztyImrm4bTwJHFxtTfnJfwnwkWtP9LQeWCjwoO0sKPFEz3KD5Ni6QzJViWgOZjbDtvCCAOM3Md";
                v.IsEn = true;
                v.ParentId = AddDictionary();
                context.Set<Dictionary>().Add(v);
                context.SaveChanges();
            }
            PartialViewResult rv = (PartialViewResult)_controller.Delete(v.ID.ToString());
            Assert.IsInstanceOfType(rv.Model, typeof(DictionaryVM));
            DictionaryVM vm = rv.Model as DictionaryVM;
            v = new Dictionary();
            v.ID = vm.Entity.ID;
            vm.Entity = v;
            _controller.Delete(v.ID.ToString(),null);
            using (var context = new DataContext(_seed, DBTypeEnum.Memory))
            {
                var data = context.Set<Dictionary>().Find(v.ID);
                Assert.AreEqual(data, null);
            }
        }
        [TestMethod]
        public void DetailsTest()
        {
            Dictionary v = new Dictionary();
            using (var context = new DataContext(_seed, DBTypeEnum.Memory))
            {
                v.Name = "b";
                v.Key = "xMrl9";
                v.Value = "EywYKwZjnxDmyQVwVYph9bYpAudrE9fseXiODivU84zBNHxqZv7ztyImrm4bTwJHFxtTfnJfwnwkWtP9LQeWCjwoO0sKPFEz3KD5Ni6QzJViWgOZjbDtvCCAOM3Md";
                v.IsEn = true;
                v.ParentId = AddDictionary();
                context.Set<Dictionary>().Add(v);
                context.SaveChanges();
            }
            PartialViewResult rv = (PartialViewResult)_controller.Details(v.ID.ToString());
            Assert.IsInstanceOfType(rv.Model, typeof(IBaseCRUDVM<TopBasePoco>));
            Assert.AreEqual(v.ID, (rv.Model as IBaseCRUDVM<TopBasePoco>).Entity.GetID());
        }
        [TestMethod]
        public void BatchEditTest()
        {
            Dictionary v1 = new Dictionary();
            Dictionary v2 = new Dictionary();
            using (var context = new DataContext(_seed, DBTypeEnum.Memory))
            {
                v1.Name = "b";
                v1.Key = "xMrl9";
                v1.Value = "EywYKwZjnxDmyQVwVYph9bYpAudrE9fseXiODivU84zBNHxqZv7ztyImrm4bTwJHFxtTfnJfwnwkWtP9LQeWCjwoO0sKPFEz3KD5Ni6QzJViWgOZjbDtvCCAOM3Md";
                v1.IsEn = true;
                v1.ParentId = AddDictionary();
                v2.Name = "QsFRU0Hrpj0paqSATzzz7bBy7XUEiXX3n2ochswiODO";
                v2.Key = "xpZrS27u53";
                v2.Value = "guWhKhfl1PVouMDiYmcgkvledon5IsxDS1OmRCXsI7DN5NMIKex21a9FdhlIzkPnMebXpH5Lvb2kOk0ADso6eGecpBYjRnFQcZopebKAQp1q7XghV67Mbqe7Uy";
                v2.IsEn = false;
                v2.ParentId = v1.ParentId;
                context.Set<Dictionary>().Add(v1);
                context.Set<Dictionary>().Add(v2);
                context.SaveChanges();
            }
            PartialViewResult rv = (PartialViewResult)_controller.BatchDelete(new string[] { v1.ID.ToString(), v2.ID.ToString() });
            Assert.IsInstanceOfType(rv.Model, typeof(DictionaryBatchVM));
            DictionaryBatchVM vm = rv.Model as DictionaryBatchVM;
            vm.Ids = new string[] { v1.ID.ToString(), v2.ID.ToString() };
            vm.FC = new Dictionary<string, object>();
            _controller.DoBatchEdit(vm, null);
            using (var context = new DataContext(_seed, DBTypeEnum.Memory))
            {
                var data1 = context.Set<Dictionary>().Find(v1.ID);
                var data2 = context.Set<Dictionary>().Find(v2.ID);
            }
        }
        [TestMethod]
        public void BatchDeleteTest()
        {
            Dictionary v1 = new Dictionary();
            Dictionary v2 = new Dictionary();
            using (var context = new DataContext(_seed, DBTypeEnum.Memory))
            {
                v1.Name = "b";
                v1.Key = "xMrl9";
                v1.Value = "EywYKwZjnxDmyQVwVYph9bYpAudrE9fseXiODivU84zBNHxqZv7ztyImrm4bTwJHFxtTfnJfwnwkWtP9LQeWCjwoO0sKPFEz3KD5Ni6QzJViWgOZjbDtvCCAOM3Md";
                v1.IsEn = true;
                v1.ParentId = AddDictionary();
                v2.Name = "QsFRU0Hrpj0paqSATzzz7bBy7XUEiXX3n2ochswiODO";
                v2.Key = "xpZrS27u53";
                v2.Value = "guWhKhfl1PVouMDiYmcgkvledon5IsxDS1OmRCXsI7DN5NMIKex21a9FdhlIzkPnMebXpH5Lvb2kOk0ADso6eGecpBYjRnFQcZopebKAQp1q7XghV67Mbqe7Uy";
                v2.IsEn = false;
                v2.ParentId = v1.ParentId;
                context.Set<Dictionary>().Add(v1);
                context.Set<Dictionary>().Add(v2);
                context.SaveChanges();
            }
            PartialViewResult rv = (PartialViewResult)_controller.BatchDelete(new string[] { v1.ID.ToString(), v2.ID.ToString() });
            Assert.IsInstanceOfType(rv.Model, typeof(DictionaryBatchVM));
            DictionaryBatchVM vm = rv.Model as DictionaryBatchVM;
            vm.Ids = new string[] { v1.ID.ToString(), v2.ID.ToString() };
            _controller.DoBatchDelete(vm, null);
            using (var context = new DataContext(_seed, DBTypeEnum.Memory))
            {
                var data1 = context.Set<Dictionary>().Find(v1.ID);
                var data2 = context.Set<Dictionary>().Find(v2.ID);
                Assert.AreEqual(data1, null);
            Assert.AreEqual(data2, null);
            }
        }
        private Guid AddDictionary()
        {
            Dictionary v = new Dictionary();
            using (var context = new DataContext(_seed, DBTypeEnum.Memory))
            {
                try{
                v.Name = "SP8IclP";
                v.Key = "dpuu";
                v.Value = "umUUGsNG3WGFIQnAVwzjcLncu32tsbKnwmsdNxeZP20qaqTdQ2Soi1J2k5Y2x68gHiUOv";
                v.IsEn = false;
                context.Set<Dictionary>().Add(v);
                context.SaveChanges();
                }
                catch{}
            }
            return v.ID;
        }
    }
}
cy_scdz.Test/Properties/launchSettings.json
New file
@@ -0,0 +1,12 @@
{
  "profiles": {
    "cy_scdz.Test": {
      "commandName": "Project",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "https://localhost:50665;http://localhost:50666"
    }
  }
}
cy_scdz.ViewModel/Setting/SettingListVM.cs
New file
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace cy_scdz.ViewModel.Setting
{
    public class SettingListVM
    {
    }
}
cy_scdz.ViewModel/Setting/SettingVm.cs
New file
@@ -0,0 +1,108 @@
using cy_scdz.Model.Set;
using Elsa.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using utils;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Extensions;
namespace cy_scdz.ViewModel.Setting
{
    public partial class SettingVm:BaseCRUDVM<Dictionary>
    {
      public  List<Dictionary> allNodesWithChildren= new List<Dictionary>();
        public SettingVm()
        {
            SetInclude(x => x.Parent);
        }
        protected override void InitVM()
        {
            allNodesWithChildren = DC.Set<Dictionary>().Where(x=>x.Parent==null)
                .Include(x=>x.Children)
      .ThenInclude(c => c.Children)
      .ToList();
        }
        public override void DoAdd()
        {
            base.DoAdd();
        }
        /// <summary>
        /// 增加一个新的字典
        /// </summary>
        /// <param name="name">名称</param>
        /// <param name="PKey">父建key</param>
        /// <param name="Key">自身key</param>
        /// <param name="value">值</param>
        public void addNew(string name, string? PKey=null,string? Key=null, string? value = null)
        {
            Dictionary Pd = null;
            if(!string.IsNullOrEmpty(PKey))
            {
                Pd= DC.Set<Dictionary>().Where(x => x.IsEn == true && x.Key == PKey).FirstOrDefault();
                if(Pd==null)
                {
                    MSD.AddModelError("ParentId", "没有找到上级信息");
                    return;
                }
            }
            Entity = new Dictionary()
            {
                Key = Key?? utilsFun.GenerateRandomString(10),
                Value = value,
                Name = name,
                IsEn = true,
                ParentId = Pd == null ? null : Pd.ID,
            };
            SetDuplicatedCheck();
            Validate();
            base.DoAdd();
        }
        public override void Validate()
        {
            base.Validate();
        }
        public override DuplicatedInfo<Dictionary> SetDuplicatedCheck()
        {
            var rv = CreateFieldsInfo(SimpleField(x => x.Name), SimpleField(x=>x.ParentId));
            rv.AddGroup(SimpleField(x => x.Key));
            return rv;
        }
        public override void DoEdit(bool updateAllFields = false)
        {
            base.DoEdit(updateAllFields);
        }
        public override void DoDelete()
        {
            base.DoDelete();
        }
    }
}
cy_scdz.ViewModel/cy_scdz.ViewModel.csproj
@@ -9,6 +9,7 @@
  <ItemGroup>
    <ProjectReference Include="..\cy_scdz.Model\cy_scdz.Model.csproj" />
  </ItemGroup >
    <ProjectReference Include="..\utils\utils.csproj" />
  </ItemGroup>
</Project>
cy_scdz.ViewModel/dictionary/DictionaryVMs/DictionaryBatchVM.cs
New file
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Extensions;
using cy_scdz.Model.Set;
namespace cy_scdz.ViewModel.dictionary.DictionaryVMs
{
    public partial class DictionaryBatchVM : BaseBatchVM<Dictionary, Dictionary_BatchEdit>
    {
        public DictionaryBatchVM()
        {
            ListVM = new DictionaryListVM();
            LinkedVM = new Dictionary_BatchEdit();
        }
    }
    /// <summary>
    /// Class to define batch edit fields
    /// </summary>
    public class Dictionary_BatchEdit : BaseVM
    {
        protected override void InitVM()
        {
        }
    }
}
cy_scdz.ViewModel/dictionary/DictionaryVMs/DictionaryImportVM.cs
New file
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Extensions;
using cy_scdz.Model.Set;
namespace cy_scdz.ViewModel.dictionary.DictionaryVMs
{
    public partial class DictionaryTemplateVM : BaseTemplateVM
    {
        [Display(Name = "名称")]
        public ExcelPropety Name_Excel = ExcelPropety.CreateProperty<Dictionary>(x => x.Name);
        [Display(Name = "Key")]
        public ExcelPropety Key_Excel = ExcelPropety.CreateProperty<Dictionary>(x => x.Key);
        [Display(Name = "值")]
        public ExcelPropety Value_Excel = ExcelPropety.CreateProperty<Dictionary>(x => x.Value);
        [Display(Name = "是否有效")]
        public ExcelPropety IsEn_Excel = ExcelPropety.CreateProperty<Dictionary>(x => x.IsEn);
        [Display(Name = "_Admin.Parent")]
        public ExcelPropety Parent_Excel = ExcelPropety.CreateProperty<Dictionary>(x => x.ParentId);
        protected override void InitVM()
        {
            Parent_Excel.DataType = ColumnDataType.ComboBox;
            Parent_Excel.ListItems = DC.Set<Dictionary>().GetSelectListItems(Wtm, y => y.Name);
        }
    }
    public class DictionaryImportVM : BaseImportVM<DictionaryTemplateVM, Dictionary>
    {
    }
}
cy_scdz.ViewModel/dictionary/DictionaryVMs/DictionaryListVM.cs
New file
@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Extensions;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using cy_scdz.Model.Set;
namespace cy_scdz.ViewModel.dictionary.DictionaryVMs
{
    public partial class DictionaryListVM : BasePagedListVM<Dictionary_View, DictionarySearcher>
    {
        protected override List<GridAction> InitGridAction()
        {
            return new List<GridAction>
            {
                this.MakeStandardAction("Dictionary", GridActionStandardTypesEnum.Create, Localizer["Sys.Create"],"dictionary", dialogWidth: 800),
                this.MakeStandardAction("Dictionary", GridActionStandardTypesEnum.Edit, Localizer["Sys.Edit"], "dictionary", dialogWidth: 800),
                this.MakeStandardAction("Dictionary", GridActionStandardTypesEnum.Delete, Localizer["Sys.Delete"], "dictionary", dialogWidth: 800),
                this.MakeStandardAction("Dictionary", GridActionStandardTypesEnum.Details, Localizer["Sys.Details"], "dictionary", dialogWidth: 800),
                this.MakeStandardAction("Dictionary", GridActionStandardTypesEnum.BatchEdit, Localizer["Sys.BatchEdit"], "dictionary", dialogWidth: 800),
                this.MakeStandardAction("Dictionary", GridActionStandardTypesEnum.BatchDelete, Localizer["Sys.BatchDelete"], "dictionary", dialogWidth: 800),
                this.MakeStandardAction("Dictionary", GridActionStandardTypesEnum.Import, Localizer["Sys.Import"], "dictionary", dialogWidth: 800),
                this.MakeStandardAction("Dictionary", GridActionStandardTypesEnum.ExportExcel, Localizer["Sys.Export"], "dictionary"),
            };
        }
        protected override IEnumerable<IGridColumn<Dictionary_View>> InitGridHeader()
        {
            return new List<GridColumn<Dictionary_View>>{
                this.MakeGridHeader(x => x.Name),
                this.MakeGridHeader(x => x.Key),
                this.MakeGridHeader(x => x.Value),
                this.MakeGridHeader(x => x.IsEn),
                this.MakeGridHeader(x => x.Name_view),
                this.MakeGridHeaderAction(width: 200)
            };
        }
        public override IOrderedQueryable<Dictionary_View> GetSearchQuery()
        {
            var query = DC.Set<Dictionary>()
                .CheckContain(Searcher.Name, x=>x.Name)
                .CheckContain(Searcher.Key, x=>x.Key)
                .CheckEqual(Searcher.IsEn, x=>x.IsEn)
                .CheckEqual(Searcher.ParentId, x=>x.ParentId)
                .Select(x => new Dictionary_View
                {
                    ID = x.ID,
                    Name = x.Name,
                    Key = x.Key,
                    Value = x.Value,
                    IsEn = x.IsEn,
                    Name_view = x.Parent.Name,
                })
                .OrderBy(x => x.ID);
            return query;
        }
    }
    public class Dictionary_View : Dictionary{
        [Display(Name = "上级名称")]
        public String Name_view { get; set; }
    }
}
cy_scdz.ViewModel/dictionary/DictionaryVMs/DictionarySearcher.cs
New file
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Extensions;
using cy_scdz.Model.Set;
namespace cy_scdz.ViewModel.dictionary.DictionaryVMs
{
    public partial class DictionarySearcher : BaseSearcher
    {
        [Display(Name = "名称")]
        public String Name { get; set; }
        [Display(Name = "Key")]
        public String Key { get; set; }
        [Display(Name = "是否有效")]
        public Boolean? IsEn { get; set; }
        public List<ComboSelectListItem> AllParents { get; set; }
        [Display(Name = "_Admin.Parent")]
        public Guid? ParentId { get; set; }
        protected override void InitVM()
        {
            AllParents = DC.Set<Dictionary>().Where(x=>x.Parent==null).GetSelectListItems(Wtm, y => y.Name);
        }
    }
}
cy_scdz.ViewModel/dictionary/DictionaryVMs/DictionaryVM.cs
New file
@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Extensions;
using cy_scdz.Model.Set;
using utils;
namespace cy_scdz.ViewModel.dictionary.DictionaryVMs
{
    public partial class DictionaryVM : BaseCRUDVM<Dictionary>
    {
        public List<ComboSelectListItem> AllParents { get; set; }
        public DictionaryVM()
        {
            SetInclude(x => x.Parent);
        }
        protected override void InitVM()
        {
            AllParents = DC.Set<Dictionary>().Where(x => x.Parent == null).GetSelectListItems(Wtm, y => y.Name);
        }
        public override void DoAdd()
        {
            base.DoAdd();
        }
        public override DuplicatedInfo<Dictionary> SetDuplicatedCheck()
        {
            var rv = CreateFieldsInfo(SimpleField(x => x.Name));
            rv.AddGroup(SimpleField(x => x.Key));
            return rv;
        }
        public override void DoEdit(bool updateAllFields = false)
        {
            base.DoEdit(updateAllFields);
        }
        public override void DoDelete()
        {
            base.DoDelete();
        }
        /// <summary>
        /// 增加一个新的字典
        /// </summary>
        /// <param name="name">名称</param>
        /// <param name="PKey">父建key</param>
        /// <param name="Key">自身key</param>
        /// <param name="value">值</param>
        public void addNew(string name, string? PKey = null, string? Key = null, string? value = null)
        {
            Dictionary Pd = null;
            if (!string.IsNullOrEmpty(PKey))
            {
                Pd = DC.Set<Dictionary>().Where(x => x.IsEn == true && x.Key == PKey).FirstOrDefault();
                if (Pd == null)
                {
                    MSD.AddModelError("ParentId", "没有找到上级信息");
                    return;
                }
            }
            Entity = new Dictionary()
            {
                Key = Key ?? utilsFun.GenerateRandomString(10),
                Value = value,
                Name = name,
                IsEn = true,
                ParentId = Pd == null ? null : Pd.ID,
            };
            base.DoAdd();
        }
    }
}
cy_scdz.sln
@@ -1,41 +1,50 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.329
# Visual Studio Version 17
VisualStudioVersion = 17.7.33913.275
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cy_scdz", "cy_scdz\cy_scdz.csproj", "{35deb565-b3c8-49dc-9fc4-19e977787c6b}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cy_scdz", "cy_scdz\cy_scdz.csproj", "{35DEB565-B3C8-49DC-9FC4-19E977787C6B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cy_scdz.Model", "cy_scdz.Model\cy_scdz.Model.csproj", "{cc774f56-bf88-4dd3-8ffc-87ceb3fe52a3}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cy_scdz.Model", "cy_scdz.Model\cy_scdz.Model.csproj", "{CC774F56-BF88-4DD3-8FFC-87CEB3FE52A3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cy_scdz.DataAccess", "cy_scdz.DataAccess\cy_scdz.DataAccess.csproj", "{ccbaa8ef-1f00-4cce-bdc8-9e96bd5bcdf0}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cy_scdz.DataAccess", "cy_scdz.DataAccess\cy_scdz.DataAccess.csproj", "{CCBAA8EF-1F00-4CCE-BDC8-9E96BD5BCDF0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cy_scdz.ViewModel", "cy_scdz.ViewModel\cy_scdz.ViewModel.csproj", "{7475cd53-adf6-4b85-a508-033c92b6c150}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cy_scdz.ViewModel", "cy_scdz.ViewModel\cy_scdz.ViewModel.csproj", "{7475CD53-ADF6-4B85-A508-033C92B6C150}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cy_scdz.Test", "cy_scdz.Test\cy_scdz.Test.csproj", "{d2ded4e0-0b1b-4822-9dd7-4a531dea14af}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cy_scdz.Test", "cy_scdz.Test\cy_scdz.Test.csproj", "{D2DED4E0-0B1B-4822-9DD7-4A531DEA14AF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "utils", "utils\utils.csproj", "{C4D69150-D72A-463D-A026-9F5785677495}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|Any CPU = Debug|Any CPU
        Release|Any CPU = Release|Any CPU
    EndGlobalSection
    GlobalSection(ProjectConfigurationPlatforms) = postSolution
        {35deb565-b3c8-49dc-9fc4-19e977787c6b}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {35deb565-b3c8-49dc-9fc4-19e977787c6b}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {35deb565-b3c8-49dc-9fc4-19e977787c6b}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {35deb565-b3c8-49dc-9fc4-19e977787c6b}.Release|Any CPU.Build.0 = Release|Any CPU
        {cc774f56-bf88-4dd3-8ffc-87ceb3fe52a3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {cc774f56-bf88-4dd3-8ffc-87ceb3fe52a3}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {cc774f56-bf88-4dd3-8ffc-87ceb3fe52a3}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {cc774f56-bf88-4dd3-8ffc-87ceb3fe52a3}.Release|Any CPU.Build.0 = Release|Any CPU
        {ccbaa8ef-1f00-4cce-bdc8-9e96bd5bcdf0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {ccbaa8ef-1f00-4cce-bdc8-9e96bd5bcdf0}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {ccbaa8ef-1f00-4cce-bdc8-9e96bd5bcdf0}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {ccbaa8ef-1f00-4cce-bdc8-9e96bd5bcdf0}.Release|Any CPU.Build.0 = Release|Any CPU
        {7475cd53-adf6-4b85-a508-033c92b6c150}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {7475cd53-adf6-4b85-a508-033c92b6c150}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {7475cd53-adf6-4b85-a508-033c92b6c150}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {7475cd53-adf6-4b85-a508-033c92b6c150}.Release|Any CPU.Build.0 = Release|Any CPU
        {35DEB565-B3C8-49DC-9FC4-19E977787C6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {35DEB565-B3C8-49DC-9FC4-19E977787C6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {35DEB565-B3C8-49DC-9FC4-19E977787C6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {35DEB565-B3C8-49DC-9FC4-19E977787C6B}.Release|Any CPU.Build.0 = Release|Any CPU
        {CC774F56-BF88-4DD3-8FFC-87CEB3FE52A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {CC774F56-BF88-4DD3-8FFC-87CEB3FE52A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {CC774F56-BF88-4DD3-8FFC-87CEB3FE52A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {CC774F56-BF88-4DD3-8FFC-87CEB3FE52A3}.Release|Any CPU.Build.0 = Release|Any CPU
        {CCBAA8EF-1F00-4CCE-BDC8-9E96BD5BCDF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {CCBAA8EF-1F00-4CCE-BDC8-9E96BD5BCDF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {CCBAA8EF-1F00-4CCE-BDC8-9E96BD5BCDF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {CCBAA8EF-1F00-4CCE-BDC8-9E96BD5BCDF0}.Release|Any CPU.Build.0 = Release|Any CPU
        {7475CD53-ADF6-4B85-A508-033C92B6C150}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {7475CD53-ADF6-4B85-A508-033C92B6C150}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {7475CD53-ADF6-4B85-A508-033C92B6C150}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {7475CD53-ADF6-4B85-A508-033C92B6C150}.Release|Any CPU.Build.0 = Release|Any CPU
        {D2DED4E0-0B1B-4822-9DD7-4A531DEA14AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {D2DED4E0-0B1B-4822-9DD7-4A531DEA14AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {D2DED4E0-0B1B-4822-9DD7-4A531DEA14AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {D2DED4E0-0B1B-4822-9DD7-4A531DEA14AF}.Release|Any CPU.Build.0 = Release|Any CPU
        {C4D69150-D72A-463D-A026-9F5785677495}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {C4D69150-D72A-463D-A026-9F5785677495}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {C4D69150-D72A-463D-A026-9F5785677495}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {C4D69150-D72A-463D-A026-9F5785677495}.Release|Any CPU.Build.0 = Release|Any CPU
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
cy_scdz/Areas/Setting/Controllers/SettingController.cs
New file
@@ -0,0 +1,65 @@
using cy_scdz.ViewModel.dictionary.DictionaryVMs;
using cy_scdz.ViewModel.Setting;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Mvc;
namespace cy_scdz.Areas.Setting.Controllers
{
    [Area("Setting")]
    [ActionDescription("系统设置")]
    public class SettingController : BaseController
    {
        #region Edit
        [ActionDescription("系统设置")]
        public ActionResult Index()
        {
            var vm = Wtm.CreateVM<SettingVm>();
            return PartialView(vm);
        }
        [ActionDescription("系统设置")]
        [HttpPost]
        public ActionResult Edit ([FromBody]EditSettingParam Param)
        {
            if (string.IsNullOrEmpty(Param.key))
                return Ok(new { code = 0});
            var vm= Wtm.CreateVM<SettingVm>(passInit:true);
            vm.addNew(Param.name, Param.key);
            if(vm.MSD.IsValid)
            {
                return Ok(new { code = 1 });
            }
            else
            return Ok(new { code = 0,msg=vm.MSD.GetFirstError()});
        }
        #endregion
    }
    /// <summary>
    /// 增加设置输入参数模型
    /// </summary>
    public class EditSettingParam
    {
        /// <summary>
        /// keyname
        /// </summary>
        [Required]
        public string key { get; set; }
        /// <summary>
        /// 名称
        /// </summary>
        [Required]
        public string name { get; set; }
    }
}
cy_scdz/Areas/Setting/Views/Setting/index.cshtml
New file
@@ -0,0 +1,169 @@
@model cy_scdz.ViewModel.Setting.SettingVm
@inject IStringLocalizer<Program> Localizer;
@for (int i = 0; i < Model.allNodesWithChildren.Count; i++)
{
    <div class="setfix set_allitem">
        <div class="content">
            <div class="text-justified bold-text tabsetsys">  @Model.allNodesWithChildren[i].Name:</div>
        </div>
        <div class="setfix">
            @for (int ix = 0; ix < Model.allNodesWithChildren[i].Children.Count; ix++)
            {
                <div class="content">
                    <div class="text-justified  itemsetsys">  @Model.allNodesWithChildren[i].Children.ToArray()[ix].Name</div>
                </div>
            }
            @if (Model.allNodesWithChildren[i].Key == "zbgys" || Model.allNodesWithChildren[i].Key == "fmzz" || Model.allNodesWithChildren[i].Key == "nyzz")
            {
                <button class="itemsetbutsys layui-btn-submit" id="@Model.allNodesWithChildren[i].Key">自定义增加</button>
            }
        </div>
    </div>
}
<style>
    .set_allitem {
        margin: 5px 0px;
    }
    .set_content {
        width: 100%;
        text-align: justify;
    }
    .text-justified {
        text-align: justify;
    }
        /* 对于现代浏览器(包括IE10+)的完整支持,可以添加以下样式以处理最后一行 */
        .text-justified:last-child::after {
            content: "";
            display: inline-block;
            width: 100%;
        }
    .font-black {
        color: #000000;
        /* 或者简写为 */
        color: black;
    }
    .bold-text {
        font-weight: bold;
    }
    .setfix {
        display: flex;
        height: 20px;
    }
    .tabsetsys {
        /* 标题偏移*/
        padding-left: 10px;
        width: 80px;
    }
    .itemsetbutsys {
        margin: 0px 10px;
    }
    .itemsetsys {
        /* 标题偏移*/
        padding: 0px 10px;
    }
</style>
<script>
    layui.use(['layer', 'jquery'], function () {
        var layer = layui.layer;
        var $ = layui.jquery;
        // 为所有具有特定类名(如:layui-btn-submit)的按钮绑定点击事件
        $('.layui-btn-submit').on('click', function (event) {
            event.preventDefault(); // 阻止默认行为
            // 获取当前点击按钮的id属性值
            var buttonId = "";
            switch (this.id) {
                case 'zbgys':
                    buttonId = "请输入新增中标供应商名称";
                    break;
                case 'fmzz':
                    buttonId = "请输入新增封面纸张规格";
                    break;
                case 'nyzz':
                    buttonId = "请输入新增内页纸张规格";
                    break;
                default:
                    buttonId = "";
                    break;
            }
            var btid = this.id;
            // 弹出一个对话框让用户输入内容
            layer.prompt({
                title: buttonId,
                formType: 0 // 0 表示文本输入框
            }, function (value, index, elem) {
                // 在这里执行提交逻辑,例如向服务器发送数据等
                submitData(btid, value, index);
            });
        });
        function submitData(id, value, index) {
            $.ajax({
                url: "/Setting/Setting/Edit",
                type: "POST"
                , contentType: "application/json; charset=utf-8"
                , dataType: "json"
                , data: JSON.stringify({ key: id, name: value })
                , success: function (result) {
                    debugger
                    if (result.code == 1) {
                        window.location.reload();
                        layer.alert(`写入成功`, {
                            icon: 0, // 设置图标为警告图标
                            title: '提示'
                        });
                        // 关闭对话框
                        layer.close(index);
                        return;
                    }
                    else {
                        layer.alert(`写入失败:${result.msg}`, {
                            icon: 2, // 设置图标为警告图标
                            title: '提示'
                        });
                        return;
                    }
                },
                    error: function (xhr, status, error) {
                        layer.alert(`系统错误:${error}`, {
                            icon: 2, // 设置图标为警告图标
                            title: '提示'
                        });
                        return;
                    }
                });
        }
    });
</script>
cy_scdz/Areas/dictionary/Controllers/DictionaryController.cs
New file
@@ -0,0 +1,219 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Mvc;
using WalkingTec.Mvvm.Core.Extensions;
using cy_scdz.ViewModel.dictionary.DictionaryVMs;
namespace cy_scdz.Controllers
{
    [Area("dictionary")]
    [ActionDescription("字典管理")]
    public partial class DictionaryController : BaseController
    {
        #region Search
        [ActionDescription("Sys.Search")]
        public ActionResult Index()
        {
            var vm = Wtm.CreateVM<DictionaryListVM>();
            return PartialView(vm);
        }
        [ActionDescription("Sys.Search")]
        [HttpPost]
        public string Search(DictionarySearcher searcher)
        {
            var vm = Wtm.CreateVM<DictionaryListVM>(passInit: true);
            if (ModelState.IsValid)
            {
                vm.Searcher = searcher;
                return vm.GetJson(false);
            }
            else
            {
                return vm.GetError();
            }
        }
        #endregion
        #region Create
        [ActionDescription("Sys.Create")]
        public ActionResult Create()
        {
            var vm = Wtm.CreateVM<DictionaryVM>();
            return PartialView(vm);
        }
        [HttpPost]
        [ActionDescription("Sys.Create")]
        public ActionResult Create(DictionaryVM vm)
        {
            if (!ModelState.IsValid)
            {
                return PartialView(vm);
            }
            else
            {
                vm.DoAdd();
                if (!ModelState.IsValid)
                {
                    vm.DoReInit();
                    return PartialView(vm);
                }
                else
                {
                    return FFResult().CloseDialog().RefreshGrid();
                }
            }
        }
        #endregion
        #region Edit
        [ActionDescription("Sys.Edit")]
        public ActionResult Edit(string id)
        {
            var vm = Wtm.CreateVM<DictionaryVM>(id);
            return PartialView(vm);
        }
        [ActionDescription("Sys.Edit")]
        [HttpPost]
        [ValidateFormItemOnly]
        public ActionResult Edit(DictionaryVM vm)
        {
            if (!ModelState.IsValid)
            {
                return PartialView(vm);
            }
            else
            {
                vm.DoEdit();
                if (!ModelState.IsValid)
                {
                    vm.DoReInit();
                    return PartialView(vm);
                }
                else
                {
                    return FFResult().CloseDialog().RefreshGridRow(vm.Entity.ID);
                }
            }
        }
        #endregion
        #region Delete
        [ActionDescription("Sys.Delete")]
        public ActionResult Delete(string id)
        {
            var vm = Wtm.CreateVM<DictionaryVM>(id);
            return PartialView(vm);
        }
        [ActionDescription("Sys.Delete")]
        [HttpPost]
        public ActionResult Delete(string id, IFormCollection nouse)
        {
            var vm = Wtm.CreateVM<DictionaryVM>(id);
            vm.DoDelete();
            if (!ModelState.IsValid)
            {
                return PartialView(vm);
            }
            else
            {
                return FFResult().CloseDialog().RefreshGrid();
            }
        }
        #endregion
        #region Details
        [ActionDescription("Sys.Details")]
        public ActionResult Details(string id)
        {
            var vm = Wtm.CreateVM<DictionaryVM>(id);
            return PartialView(vm);
        }
        #endregion
        #region BatchEdit
        [HttpPost]
        [ActionDescription("Sys.BatchEdit")]
        public ActionResult BatchEdit(string[] IDs)
        {
            var vm = Wtm.CreateVM<DictionaryBatchVM>(Ids: IDs);
            return PartialView(vm);
        }
        [HttpPost]
        [ActionDescription("Sys.BatchEdit")]
        public ActionResult DoBatchEdit(DictionaryBatchVM vm, IFormCollection nouse)
        {
            if (!ModelState.IsValid || !vm.DoBatchEdit())
            {
                return PartialView("BatchEdit",vm);
            }
            else
            {
                return FFResult().CloseDialog().RefreshGrid().Alert(Localizer["Sys.BatchEditSuccess", vm.Ids.Length]);
            }
        }
        #endregion
        #region BatchDelete
        [HttpPost]
        [ActionDescription("Sys.BatchDelete")]
        public ActionResult BatchDelete(string[] IDs)
        {
            var vm = Wtm.CreateVM<DictionaryBatchVM>(Ids: IDs);
            return PartialView(vm);
        }
        [HttpPost]
        [ActionDescription("Sys.BatchDelete")]
        public ActionResult DoBatchDelete(DictionaryBatchVM vm, IFormCollection nouse)
        {
            if (!ModelState.IsValid || !vm.DoBatchDelete())
            {
                return PartialView("BatchDelete",vm);
            }
            else
            {
                return FFResult().CloseDialog().RefreshGrid().Alert(Localizer["Sys.BatchDeleteSuccess", vm.Ids.Length]);
            }
        }
        #endregion
        #region Import
        [ActionDescription("Sys.Import")]
        public ActionResult Import()
        {
            var vm = Wtm.CreateVM<DictionaryImportVM>();
            return PartialView(vm);
        }
        [HttpPost]
        [ActionDescription("Sys.Import")]
        public ActionResult Import(DictionaryImportVM vm, IFormCollection nouse)
        {
            if (vm.ErrorListVM.EntityList.Count > 0 || !vm.BatchSaveData())
            {
                return PartialView(vm);
            }
            else
            {
                return FFResult().CloseDialog().RefreshGrid().Alert(Localizer["Sys.ImportSuccess", vm.EntityList.Count.ToString()]);
            }
        }
        #endregion
        [ActionDescription("Sys.Export")]
        [HttpPost]
        public IActionResult ExportExcel(DictionaryListVM vm)
        {
            return vm.GetExportData();
        }
    }
}
cy_scdz/Areas/dictionary/Views/Dictionary/BatchDelete.cshtml
New file
@@ -0,0 +1,12 @@
@model cy_scdz.ViewModel.dictionary.DictionaryVMs.DictionaryBatchVM
@inject IStringLocalizer<Program> Localizer;
<wt:form vm="@Model">
    <wt:quote>@Localizer["Sys.BatchDeleteConfirm"]</wt:quote>
    <wt:hidden field="Ids" />
    <wt:grid vm="ListVM" use-local-data="true" height="300"  hidden-checkbox="true" hidden-panel="true"/>
    <wt:row align="AlignEnum.Right">
        <wt:submitbutton theme=" ButtonThemeEnum.Warm" text="@Localizer["Sys.Delete"]"/>
        <wt:closebutton />
    </wt:row>
</wt:form>
cy_scdz/Areas/dictionary/Views/Dictionary/BatchEdit.cshtml
New file
@@ -0,0 +1,14 @@
@model cy_scdz.ViewModel.dictionary.DictionaryVMs.DictionaryBatchVM
@inject IStringLocalizer<Program> Localizer;
<wt:form vm="@Model">
    <div style="margin-bottom:10px">@Localizer["Sys.BatchEditConfirm"] </div>
<wt:row items-per-row="ItemsPerRowEnum.Two">
</wt:row>
    <wt:hidden field="Ids" />
    <wt:grid vm="ListVM" use-local-data="true" height="300"  hidden-checkbox="true" hidden-panel="true"/>
    <wt:row align="AlignEnum.Right">
        <wt:submitbutton />
        <wt:closebutton />
    </wt:row>
</wt:form>
cy_scdz/Areas/dictionary/Views/Dictionary/Create.cshtml
New file
@@ -0,0 +1,16 @@
@model cy_scdz.ViewModel.dictionary.DictionaryVMs.DictionaryVM
@inject IStringLocalizer<Program> Localizer;
<wt:form vm="@Model">
<wt:row items-per-row="ItemsPerRowEnum.Two">
<wt:textbox field="Entity.Name" />
<wt:textbox field="Entity.Key" />
<wt:textbox field="Entity.Value" />
<wt:switch field="Entity.IsEn" />
<wt:combobox field="Entity.ParentId" items="AllParents"/>
</wt:row>
    <wt:row align="AlignEnum.Right">
        <wt:submitbutton />
        <wt:closebutton />
    </wt:row>
</wt:form>
cy_scdz/Areas/dictionary/Views/Dictionary/Delete.cshtml
New file
@@ -0,0 +1,18 @@
@model cy_scdz.ViewModel.dictionary.DictionaryVMs.DictionaryVM
@inject IStringLocalizer<Program> Localizer;
<wt:form vm="@Model">
    <wt:quote>@Localizer["Sys.DeleteConfirm"]</wt:quote>
<wt:row items-per-row="ItemsPerRowEnum.Two">
<wt:display field="Entity.Name" />
<wt:display field="Entity.Key" />
<wt:display field="Entity.Value" />
<wt:display field="Entity.IsEn" />
<wt:display field="Entity.Parent.Name" />
</wt:row>
    <wt:hidden field="Entity.ID" />
    <wt:row align="AlignEnum.Right">
        <wt:submitbutton theme=" ButtonThemeEnum.Warm" text="@Localizer["Sys.Delete"]"/>
        <wt:closebutton />
    </wt:row>
</wt:form>
cy_scdz/Areas/dictionary/Views/Dictionary/Details.cshtml
New file
@@ -0,0 +1,15 @@
@model cy_scdz.ViewModel.dictionary.DictionaryVMs.DictionaryVM
@inject IStringLocalizer<Program> Localizer;
<wt:form vm="@Model">
<wt:row items-per-row="ItemsPerRowEnum.Two">
<wt:display field="Entity.Name" />
<wt:display field="Entity.Key" />
<wt:display field="Entity.Value" />
<wt:display field="Entity.IsEn" />
<wt:display field="Entity.Parent.Name" />
</wt:row>
    <wt:row align="AlignEnum.Right">
        <wt:closebutton />
    </wt:row>
</wt:form>
cy_scdz/Areas/dictionary/Views/Dictionary/Edit.cshtml
New file
@@ -0,0 +1,17 @@
@model cy_scdz.ViewModel.dictionary.DictionaryVMs.DictionaryVM
@inject IStringLocalizer<Program> Localizer;
<wt:form vm="@Model">
<wt:row items-per-row="ItemsPerRowEnum.Two">
<wt:textbox field="Entity.Name" />
<wt:textbox field="Entity.Key" />
<wt:textbox field="Entity.Value" />
<wt:switch field="Entity.IsEn" />
<wt:combobox field="Entity.ParentId" items="AllParents"/>
</wt:row>
    <wt:hidden field="Entity.ID" />
    <wt:row align="AlignEnum.Right">
        <wt:submitbutton />
        <wt:closebutton />
    </wt:row>
</wt:form>
cy_scdz/Areas/dictionary/Views/Dictionary/Import.cshtml
New file
@@ -0,0 +1,14 @@
@model cy_scdz.ViewModel.dictionary.DictionaryVMs.DictionaryImportVM
@inject IStringLocalizer<Program> Localizer;
<wt:form vm="@Model">
    <wt:row align="AlignEnum.Right">
        <wt:downloadTemplateButton vm="@Model" />
    </wt:row>
    <wt:upload field="UploadFileId" label-text="@Model.Localizer["Sys.UploadTemplate"]" upload-type="ExcelFile" />
    <wt:grid vm="ErrorListVM" use-local-data="true" hidden-checkbox="true" hidden-grid-index="true" hidden-panel="true"  height="300"/>
    <wt:row align="AlignEnum.Right">
        <wt:submitbutton />
        <wt:closebutton />
    </wt:row>
</wt:form>
cy_scdz/Areas/dictionary/Views/Dictionary/Index.cshtml
New file
@@ -0,0 +1,12 @@
@model cy_scdz.ViewModel.dictionary.DictionaryVMs.DictionaryListVM
@inject IStringLocalizer<Program> Localizer;
<wt:searchpanel vm="@Model" reset-btn="true">
<wt:row items-per-row="ItemsPerRowEnum.Three">
<wt:textbox field="Searcher.Name" />
<wt:textbox field="Searcher.Key" />
<wt:combobox field="Searcher.IsEn" empty-text="@Localizer["Sys.All"]" />
<wt:combobox field="Searcher.ParentId" items="Searcher.AllParents" empty-text="@Localizer["Sys.All"]" />
</wt:row>
</wt:searchpanel>
<wt:grid vm="@Model" url="/dictionary/Dictionary/Search"/>
cy_scdz/Views/Login/Login.cshtml
@@ -71,7 +71,7 @@
              <li>
                <span class="login-error">@Model.MSD.GetFirstError()</span>
                <button type="submit" class="login-button" style="cursor:pointer">@Model.Localizer["Login.Login"]</button>
                <wt:linkbutton window-title="@Model.Localizer["Login.Register"]" class="login-button" style="cursor:pointer" target="ButtonTargetEnum.Layer" window-width="500" window-height="500" url="/Login/Reg" text="@Model.Localizer["Login.Register"]" />
                @* <wt:linkbutton window-title="@Model.Localizer["Login.Register"]" class="login-button" style="cursor:pointer" target="ButtonTargetEnum.Layer" window-width="500" window-height="500" url="/Login/Reg" text="@Model.Localizer["Login.Register"]" /> *@
              </li>
            </ul>
          </form>
cy_scdz/appsettings.json
@@ -21,14 +21,14 @@
  "Connections": [
    {
      "Key": "default",
      "Value": "Server=(localdb)\\mssqllocaldb;Database=cy_scdz_db;Trusted_Connection=True;",
      "Value": "Server=localhost\\SQLEXPRESS;Database=cy_scdz_db;Trusted_Connection=True;User ID=sa;Password=123456;",
      "DbContext": "DataContext",
      "DBType": "SqlServer" //DataBase, you can choose mysql,sqlserver,pgsql,sqlite,oracle
    }
  ],
  "CookiePre": "cy_scdz", //cookie prefix
  "IsQuickDebug": true, //is debug mode
   "EnableTenant":  true, //是否启动多租户
   "EnableTenant":  false, //是否启动多租户
   "CorsOptions": {
    "EnableAll": true
  },
cy_scdz/cy_scdz.csproj
@@ -22,7 +22,8 @@
   <ProjectReference Include="..\cy_scdz.Model\cy_scdz.Model.csproj" />
    <ProjectReference Include="..\cy_scdz.DataAccess\cy_scdz.DataAccess.csproj" />
    <ProjectReference Include="..\cy_scdz.ViewModel\cy_scdz.ViewModel.csproj" />
 </ItemGroup >
    <ProjectReference Include="..\utils\utils.csproj" />
 </ItemGroup>
</Project>
cy_scdz/cy_scdz.csproj.user
New file
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Controller_SelectedScaffolderID>MvcControllerEmptyScaffolder</Controller_SelectedScaffolderID>
    <Controller_SelectedScaffolderCategoryPath>root/Common/MVC/Controller</Controller_SelectedScaffolderCategoryPath>
    <View_SelectedScaffolderID>RazorViewEmptyScaffolder</View_SelectedScaffolderID>
    <View_SelectedScaffolderCategoryPath>root/Common/MVC/View</View_SelectedScaffolderCategoryPath>
  </PropertyGroup>
</Project>
utils/utils.csproj
New file
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
</Project>
utils/utilsFun.cs
New file
@@ -0,0 +1,27 @@
using System.Text;
namespace utils
{
    /// <summary>
    /// 通用函数库
    /// </summary>
    public static class utilsFun
    {
        private const string ValidChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-=[]{}|;:',.<>?/`~";
        public static string GenerateRandomString(int length)
        {
            StringBuilder builder = new StringBuilder();
            Random random = new Random();
            for (int i = 0; i < length; i++)
            {
                int index = random.Next(ValidChars.Length);
                char randomChar = ValidChars[index];
                builder.Append(randomChar);
            }
            return builder.ToString();
        }
    }
}