dengjunjie
2025-03-12 f43b7df8400f4fcffc9f19dca0888d61e2b33d5f
ÏîÄ¿´úÂë/WMS/WIDESEA_WMSServer/WIDESEA_Core/BaseServices/ServiceBase.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,691 @@
using Magicodes.ExporterAndImporter.Core;
using Magicodes.ExporterAndImporter.Core.Models;
using Magicodes.ExporterAndImporter.Excel;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using SqlSugar;
using System.Drawing.Drawing2D;
using System.Dynamic;
using System.Linq.Expressions;
using System.Reflection;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.Enums;
using WIDESEA_Core.Helper;
using WIDESEA_Core.Utilities;
using static OfficeOpenXml.ExcelErrorValue;
namespace WIDESEA_Core.BaseServices
{
    public class ServiceBase<TEntity, TRepository> : ServiceFunFilter<TEntity>, IService<TEntity>
         where TEntity : class, new()
         where TRepository : IRepository<TEntity>
    {
        public ServiceBase(TRepository BaseDal)
        {
            this.BaseDal = BaseDal;
        }
        public TRepository BaseDal { get; set; } //通过在子类的构造函数中注入,这里是基类,不用构造函数
        public ISqlSugarClient Db => BaseDal.Db;
        private PropertyInfo[] _propertyInfo { get; set; } = null;
        public PropertyInfo[] TProperties
        {
            get
            {
                if (_propertyInfo != null)
                {
                    return _propertyInfo;
                }
                _propertyInfo = typeof(TEntity).GetProperties();
                return _propertyInfo;
            }
        }
        public virtual PageGridData<TEntity> GetPageData(PageDataOptions options)
        {
            string wheres = options.ValidatePageOptions(TProperties);
            //获取排序字段
            Dictionary<string, OrderByType> orderbyDic = options.GetPageDataSort(TProperties);
            PageGridData<TEntity> pageGridData = new PageGridData<TEntity>();
            pageGridData = BaseDal.QueryPage(wheres, options.Page, options.Rows, orderbyDic);
            return pageGridData;
        }
        public string ValidatePageOptions(PageDataOptions options)
        {
            options = options ?? new PageDataOptions();
            string text = "";
            List<SearchParameters> searchParametersList = new List<SearchParameters>();
            if (options.Filter != null && options.Filter.Count > 0)
            {
                searchParametersList.AddRange(options.Filter);
            }
            else if (!string.IsNullOrEmpty(options.Wheres))
            {
                try
                {
                    searchParametersList = options.Wheres.DeserializeObject<List<SearchParameters>>();
                    options.Filter = searchParametersList;
                }
                catch
                {
                }
            }
            base.QueryRelativeList?.Invoke(searchParametersList);
            int i;
            for (i = 0; i < searchParametersList.Count; i++)
            {
                if (string.IsNullOrEmpty(searchParametersList[i].Value))
                {
                    continue;
                }
                PropertyInfo propertyInfo = TProperties.Where((PropertyInfo c) => c.Name.ToUpper() == searchParametersList[i].Name.ToUpper()).FirstOrDefault();
                if (propertyInfo == null)
                {
                    continue;
                }
                object[] values = searchParametersList[i].Value.Split(',');
                List<(bool, string, object)> list = propertyInfo.ValidationValueForDbType(values).ToList();
                if (list == null || list.Count() == 0)
                {
                    continue;
                }
                for (int j = 0; j < list.Count(); j++)
                {
                    if (j == 0)
                    {
                        text += "(";
                    }
                    text = ((searchParametersList[i].DisplayType.GetLinqCondition() != 0) ? (text + $"{searchParametersList[i].Name} {searchParametersList[i].DisplayType} '{list[j].Item3}'") : (text + $"{searchParametersList[i].Name} = '{list[j].Item3}'"));
                    text = ((j != list.Count() - 1) ? (text + " or ") : (text + ")"));
                }
                if (i < searchParametersList.Count - 1)
                {
                    text += " and ";
                }
            }
            return text;
        }
        public virtual object GetDetailPage(PageDataOptions pageData)
        {
            Type t = typeof(TEntity);
            if (pageData.Value == null) return new PageGridData<object>(total: 0, null);
            string keyName = t.GetKeyName();
            ////生成查询条件
            //Expression<Func<TEntity, bool>> whereExpression = keyName.CreateExpression<TEntity>(pageData.Value, LinqExpressionType.Equal);
            int totalCount = 0;
            PropertyInfo propertyInfo = t.GetProperties().FirstOrDefault(x => x.GetCustomAttribute<Navigate>() != null);
            if (propertyInfo != null)
            {
                Type detailType = propertyInfo.PropertyType.GetGenericArguments()[0];
                Navigate navigate = propertyInfo.GetCustomAttribute<Navigate>();
                List<ExpandoObject> list = BaseDal.Db.Queryable(detailType.Name, "detail").Where(navigate.GetName(), "=", pageData.Value).ToPageList(pageData.Page, pageData.Rows, ref totalCount);
                return new PageGridData<ExpandoObject>(totalCount, list);
            }
            return new PageGridData<object>(total: 0, null);
        }
        /// <summary>
        /// æ·»åŠ æ•°æ®
        /// </summary>
        /// <param name="entity">单个实体</param>
        /// <returns></returns>
        public virtual WebResponseContent AddData(TEntity entity)
        {
            try
            {
                return BaseDal.AddData(entity) > 0 ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error();
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        /// <summary>
        /// æ·»åŠ æ•°æ®
        /// </summary>
        /// <param name="entities">实体集合</param>
        /// <returns></returns>
        public virtual WebResponseContent AddData(List<TEntity> entities)
        {
            try
            {
                return BaseDal.AddData(entities) > 0 ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error();
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        /// <summary>
        /// æ·»åŠ æ•°æ®
        /// </summary>
        /// <param name="saveModel"></param>
        /// <returns></returns>
        public virtual WebResponseContent AddData(SaveModel saveModel)
        {
            try
            {
                if (saveModel == null || saveModel.MainData == null || saveModel.MainData.Count == 0)//判断参数是否传入
                {
                    return WebResponseContent.Instance.Error("传参错误,参数不能为空");
                }
                string validResult = typeof(TEntity).ValidateDicInEntity(saveModel.MainData, true, TProperties);
                if (!string.IsNullOrEmpty(validResult))
                {
                    return WebResponseContent.Instance.Error(validResult);
                }
                PropertyInfo keyPro = typeof(TEntity).GetKeyProperty();
                if (keyPro == null)
                {
                    return WebResponseContent.Instance.Error("请先设置主键");
                }
                if (keyPro.PropertyType == typeof(Guid))
                {
                    saveModel.MainData.Add(keyPro.Name, Guid.NewGuid());
                }
                else if (keyPro.PropertyType == typeof(int) || keyPro.PropertyType == typeof(long))
                {
                    SugarColumn? sugarColumn = keyPro.GetCustomAttribute<SugarColumn>();
                    if (sugarColumn?.IsIdentity ?? true)
                    {
                        saveModel.MainData.Remove(keyPro.Name.FirstLetterToUpper());
                        saveModel.MainData.Remove(keyPro.Name.FirstLetterToLower());
                    }
                }
                TEntity entity = saveModel.MainData.DicToModel<TEntity>();
                if (saveModel.DetailData == null || saveModel.DetailData.Count == 0)
                {
                    BaseDal.AddData(entity);
                    return WebResponseContent.Instance.OK();
                }
                if (typeof(TEntity).GetNavigatePro() == null)
                {
                    return WebResponseContent.Instance.Error("未配置导航属性");
                }
                Type detailType = typeof(TEntity).GetDetailType();
                MethodInfo? methodInfo = GetType().GetMethod("AddDataIncludesDetail");
                methodInfo = methodInfo?.MakeGenericMethod(new Type[] { detailType });
                object? obj = methodInfo?.Invoke(this, new object[] { entity, detailType, saveModel.DetailData });
                return obj as WebResponseContent;
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        public WebResponseContent AddDataIncludesDetail<TDetail>(TEntity entity, Type detailType, List<Dictionary<string, object>> detailDics) where TDetail : class, new()
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                string name = typeof(TEntity).GetMainIdByDetail();
                string reslut = detailType.ValidateDicInEntity(detailDics, true, new string[] { name });
                if (reslut != string.Empty)
                    return WebResponseContent.Instance.Error(reslut);
                List<TDetail> list = detailDics.DicToIEnumerable<TDetail>();
                ((SqlSugarClient)BaseDal.Db).BeginTran();
                int id = BaseDal.Db.Insertable(entity).ExecuteReturnIdentity();
                for (int i = 0; i < list.Count; i++)
                {
                    TDetail detail = list[i];
                    typeof(TDetail).SetDetailId(detail, id, name);
                }
                BaseDal.Db.Insertable(list).ExecuteCommand();
                ((SqlSugarClient)BaseDal.Db).CommitTran();
                content = WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
            {
                ((SqlSugarClient)BaseDal.Db).RollbackTran();
                content = WebResponseContent.Instance.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// ä¿®æ”¹æ•°æ®
        /// </summary>
        /// <param name="entity">单个实体</param>
        /// <returns></returns>
        public virtual WebResponseContent UpdateData(TEntity entity)
        {
            try
            {
                return BaseDal.UpdateData(entity) ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error();
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        /// <summary>
        /// ä¿®æ”¹æ•°æ®
        /// </summary>
        /// <param name="entities">实体集合</param>
        /// <returns></returns>
        public virtual WebResponseContent UpdateData(List<TEntity> entities)
        {
            try
            {
                return BaseDal.UpdateData(entities) ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error();
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        /// <summary>
        /// ä¿®æ”¹æ•°æ®
        /// </summary>
        /// <param name="saveModel"></param>
        /// <returns></returns>
        public virtual WebResponseContent UpdateData(SaveModel saveModel)
        {
            try
            {
                List<string>? list = UpdateIgnoreColOnExecute?.Invoke(saveModel);
                if (saveModel == null || saveModel.MainData == null || saveModel.MainData.Count == 0)//判断参数是否传入
                {
                    return WebResponseContent.Instance.Error("传参错误,参数不能为空");
                }
                string validResult = typeof(TEntity).ValidateDicInEntity(saveModel.MainData, false, TProperties, list?.ToArray() ?? null);
                if (!string.IsNullOrEmpty(validResult))
                {
                    return WebResponseContent.Instance.Error(validResult);
                }
                PropertyInfo keyPro = typeof(TEntity).GetKeyProperty();
                if (keyPro == null)
                {
                    return WebResponseContent.Instance.Error("请先设置主键");
                }
                TEntity entity = saveModel.MainData.DicToModel<TEntity>();
                List<string> listCol = new List<string>();
                foreach (var item in saveModel.MainData)
                {
                    PropertyInfo? propertyInfo = typeof(TEntity).GetProperty(item.Key);
                    if (propertyInfo == null)
                    {
                        propertyInfo = typeof(TEntity).GetProperty(item.Key.FirstLetterToLower());
                        if (propertyInfo == null)
                        {
                            propertyInfo = typeof(TEntity).GetProperty(item.Key.FirstLetterToUpper());
                        }
                    }
                    listCol.Add(propertyInfo?.Name);
                }
                if (saveModel.DetailData == null || saveModel.DetailData.Count == 0)
                {
                    //if (list != null)
                    //    listCol = listCol.Where(x => !list.Contains(x)).ToList();
                    bool result = BaseDal.UpdateData(entity/*, listCol, list*/);
                    return WebResponseContent.Instance.OK();
                }
                if (typeof(TEntity).GetNavigatePro() == null)
                {
                    return WebResponseContent.Instance.Error("未配置导航属性");
                }
                Type detailType = typeof(TEntity).GetDetailType();
                MethodInfo? methodInfo = GetType().GetMethod("UpdateDataInculdesDetail");
                methodInfo = methodInfo?.MakeGenericMethod(new Type[] { detailType });
                object? obj = methodInfo?.Invoke(this, new object[] { entity, detailType, saveModel.DetailData, saveModel.DelKeys });
                return obj as WebResponseContent;
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        public WebResponseContent UpdateDataInculdesDetail<TDetail>(TEntity entity, Type detailType, List<Dictionary<string, object>> detailDics, List<object> delKeys) where TDetail : class, new()
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                string name = typeof(TEntity).GetMainIdByDetail();
                string reslut = detailType.ValidateDicInEntity(detailDics, true, new string[] { name });
                if (reslut != string.Empty)
                    return WebResponseContent.Instance.Error(reslut);
                List<TDetail> list = detailDics.DicToIEnumerable<TDetail>();
                List<object> dynamicDelKeys = new List<object>();
                if (delKeys != null)
                {
                    for (int i = 0; i < delKeys.Count; i++)
                    {
                        dynamicDelKeys.Add(delKeys[i]);
                    }
                }
                List<TDetail> updateRows = new List<TDetail>();
                List<TDetail> addRows = new List<TDetail>();
                for (int i = 0; i < list.Count; i++)
                {
                    object detailId = typeof(TDetail).GetPropertyValue(list[i], typeof(TDetail).GetKeyName());
                    if (detailId != null)
                    {
                        if (detailId.ToString() != "0")
                        {
                            updateRows.Add(list[i]);
                        }
                        else
                        {
                            addRows.Add(list[i]);
                        }
                    }
                }
                object mainId = typeof(TEntity).GetPropertyValue(entity, typeof(TEntity).GetKeyName());
                if (mainId != null)
                {
                    ((SqlSugarClient)BaseDal.Db).BeginTran();
                    if (dynamicDelKeys.Count > 0)
                        BaseDal.Db.Deleteable<object>().AS(detailType.Name).Where($"{detailType.GetKeyName()} in (@id)", new { id = dynamicDelKeys.ToArray() }).ExecuteCommandHasChange();
                    BaseDal.Db.Updateable(entity).ExecuteCommandHasChange();
                    BaseDal.Db.Updateable(updateRows).ExecuteCommand();
                    for (int i = 0; i < addRows.Count; i++)
                    {
                        TDetail detail = addRows[i];
                        typeof(TDetail).SetDetailId(detail, mainId, name);
                    }
                    BaseDal.Db.Insertable(addRows).ExecuteCommand();
                    ((SqlSugarClient)BaseDal.Db).CommitTran();
                    content = WebResponseContent.Instance.OK();
                }
                else
                {
                    content = WebResponseContent.Instance.Error("未找到主表主键值");
                }
            }
            catch (Exception ex)
            {
                ((SqlSugarClient)BaseDal.Db).RollbackTran();
                content = WebResponseContent.Instance.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// åˆ é™¤æ•°æ®
        /// </summary>
        /// <param name="key">主键</param>
        /// <returns></returns>
        public virtual WebResponseContent DeleteData(object key)
        {
            try
            {
                return BaseDal.DeleteDataById(key) ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error();
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        /// <summary>
        /// åˆ é™¤æ•°æ®
        /// </summary>
        /// <param name="keys">主键数组</param>
        /// <returns></returns>
        public virtual WebResponseContent DeleteData(object[] keys)
        {
            try
            {
                if (typeof(TEntity).GetNavigatePro() == null)
                    return BaseDal.DeleteDataByIds(keys) ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error();
                else
                {
                    if (keys != null)
                    {
                        Type detailType = typeof(TEntity).GetDetailType();
                        string name = typeof(TEntity).GetMainIdByDetail();
                        List<object> dynamicDelKeys = new List<object>();
                        for (int i = 0; i < keys.Length; i++)
                        {
                            dynamicDelKeys.Add(keys[i]);
                        }
                        ((SqlSugarClient)BaseDal.Db).BeginTran();
                        if (dynamicDelKeys.Count > 0)
                            BaseDal.Db.Deleteable<object>().AS(detailType.Name).Where($"{name} in (@id)", new { id = dynamicDelKeys.ToArray() }).ExecuteCommandHasChange();
                        BaseDal.DeleteDataByIds(keys);
                        ((SqlSugarClient)BaseDal.Db).CommitTran();
                        return WebResponseContent.Instance.OK();
                    }
                    else
                    {
                        return WebResponseContent.Instance.Error("参数错误");
                    }
                }
            }
            catch (Exception ex)
            {
                ((SqlSugarClient)BaseDal.Db).RollbackTran();
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        /// <summary>
        /// åˆ é™¤æ•°æ®
        /// </summary>
        /// <param name="entity">单个实体</param>
        /// <returns></returns>
        public virtual WebResponseContent DeleteData(TEntity entity)
        {
            try
            {
                return BaseDal.DeleteData(entity) ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error();
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        /// <summary>
        /// åˆ é™¤æ•°æ®
        /// </summary>
        /// <param name="entities">实体集合</param>
        /// <returns></returns>
        public virtual WebResponseContent DeleteData(List<TEntity> entities)
        {
            try
            {
                return BaseDal.DeleteData(entities) ? WebResponseContent.Instance.OK() : WebResponseContent.Instance.Error();
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        /// <summary>
        /// å¯¼å‡ºæ•°æ®
        /// </summary>
        /// <param name="pageData"></param>
        /// <returns></returns>
        public virtual WebResponseContent Export(PageDataOptions options)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                Type t = typeof(TEntity);
                string savePath = AppDomain.CurrentDomain.BaseDirectory + $"ExcelExport";
                IExporter exporter = new ExcelExporter();
                string wheres = options.ValidatePageOptions(TProperties);
                //获取排序字段
                Dictionary<string, OrderByType> orderbyDic = options.GetPageDataSort(TProperties);
                List<TEntity> entities = BaseDal.QueryData(wheres, orderbyDic);
                byte[] data = exporter.ExportAsByteArray(entities).Result;
                string fileName = "";
                SugarTable sugarTable = t.GetCustomAttribute<SugarTable>();
                if (sugarTable != null)
                {
                    fileName = sugarTable.TableDescription + ".xlsx";
                }
                else
                {
                    fileName = nameof(TEntity) + ".xlsx";
                }
                FileHelper.WriteFile(savePath, fileName, data);
                content = WebResponseContent.Instance.OK(data: savePath + "\\" + fileName);
            }
            catch (Exception ex)
            {
                content = WebResponseContent.Instance.Error(ex.Message);
            }
            return content;
        }
        /// <summary>
        /// å¯¼å…¥æ•°æ®
        /// </summary>
        /// <param name="files"></param>
        /// <returns></returns>
        public virtual WebResponseContent Import(List<IFormFile> files)
        {
            try
            {
                if (files == null || files.Count == 0)
                    return new WebResponseContent { Status = true, Message = "请选择上传的文件" };
                Microsoft.AspNetCore.Http.IFormFile formFile = files[0];
                string dicPath = AppDomain.CurrentDomain.BaseDirectory + $"ExcelImprot/{DateTime.Now.ToString("yyyMMdd")}/{typeof(TEntity).Name}/";
                if (!Directory.Exists(dicPath)) Directory.CreateDirectory(dicPath);
                string fileName = $"{Guid.NewGuid()}_{formFile.FileName}";
                dicPath = $"{dicPath}{fileName}";
                using (FileStream stream = new FileStream(dicPath, FileMode.Create))
                {
                    formFile.CopyTo(stream);
                }
                ExcelImporter importer = new ExcelImporter();
                ImportResult<TEntity> importResult = importer.Import<TEntity>(dicPath, "").Result;
                if (importResult.HasError)
                {
                    return WebResponseContent.Instance.Error(importResult.TemplateErrors.Serialize());
                }
                BaseDal.AddData(importResult.Data.ToList());
                return WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        /// <summary>
        /// ä¸Šä¼ æ–‡ä»¶
        /// </summary>
        /// <param name="files"></param>
        /// <returns></returns>
        public virtual WebResponseContent Upload(List<IFormFile> files)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// æ¨¡æ¿ä¸‹è½½
        /// </summary>
        /// <returns></returns>
        public virtual WebResponseContent DownLoadTemplate()
        {
            WebResponseContent content = new WebResponseContent();
            Type t = typeof(TEntity);
            IExporter exporter = new ExcelExporter();
            byte[] data = exporter.ExportHeaderAsByteArray(new TEntity()).Result;
            string fileName = "";
            SugarTable sugarTable = t.GetCustomAttribute<SugarTable>();
            if (sugarTable != null)
            {
                fileName = sugarTable.TableDescription + "导入模板.xlsx";
            }
            else
            {
                fileName = nameof(TEntity) + "导入模板.xlsx";
            }
            string savePath = AppDomain.CurrentDomain.BaseDirectory + $"ExcelImprotTemplate";
            FileHelper.WriteFile(savePath, fileName, data);
            content = WebResponseContent.Instance.OK(data: savePath + "\\" + fileName);
            return content;
        }
        public WebResponseContent ExportSeedData()
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                string seedDataFolder = $"WIDESEA_DB.DBSeed.Json/{typeof(TEntity).Name}.tsv";
                List<TEntity> deviceInfos = BaseDal.QueryData();
                string str = JsonConvert.SerializeObject(deviceInfos, Formatting.Indented);
                List<Dictionary<string, object>> keyValuePairs = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(str);
                FileHelper.WriteFileAndDelOldFile($"{AppDomain.CurrentDomain.BaseDirectory}wwwroot/{seedDataFolder}", str);
                content = WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
            {
                content = WebResponseContent.Instance.Error(ex.Message);
            }
            return content;
        }
    }
}