| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 | using System.Text.Encodings.Web;using System.Text.Json;namespace OASystem.Domain.Entities.Groups{    /// <summary>    /// 签证流程管控步骤    /// </summary>    [SugarTable(tableName: "Grp_VisaProcessSteps", TableDescription = "签证流程步骤")]    public class Grp_VisaProcessSteps : EntityBase    {        /// <summary>        /// 团组Id(Grp_DelegationInfo)        /// </summary>        [SugarColumn(ColumnName = "GroupId", ColumnDescription = "团组Id(Grp_DelegationInfo)", IsNullable = true, ColumnDataType = "int")]        public int GroupId { get; set; }        /// <summary>        /// 步骤        /// </summary>        [SugarColumn(ColumnName = "Step", ColumnDescription = "步骤", IsNullable = true, ColumnDataType = "int")]        public int Step { get; set; }        /// <summary>        /// 标识数据类型        /// </summary>        [SugarColumn(ColumnName = "DataType", ColumnDescription = "标识数据类型", IsNullable = true, ColumnDataType = "varchar(50)")]        public string DataType { get; set; }        /// <summary>        /// 存储值(办理日期(2025-01-01))、bool(false,true))        /// </summary>        [SugarColumn(ColumnName = "StoreVal", ColumnDescription = "存储值(办理日期(2025-01-01))、bool(false,true))", IsNullable = true, ColumnDataType = "varchar(max)")]        public string StoreVal { get; set; }        /// <summary>        /// 附件地址        /// </summary>        [SugarColumn(ColumnName = "AttachUrl", ColumnDescription = "附件地址", IsNullable = true, ColumnDataType = "varchar(max)")]        public string AttachUrl { get; set; }        /// <summary>        /// 是否确认完成        /// </summary>        [SugarColumn(ColumnName = "IsCompleted", ColumnDescription = "确认完成", IsNullable = true, ColumnDataType = "bit")]        public bool IsCompleted { get; set; } = false;        /// <summary>        /// 最后更新人        /// </summary>        [SugarColumn(ColumnName = "LastUpdateUserId", ColumnDescription = "最后更新人", IsNullable = true, ColumnDataType = "int")]        public int LastUpdateUserId { get; set; }        /// <summary>        /// 最后更新时间        /// </summary>        [SugarColumn(ColumnName = "LastUpdateTime", ColumnDescription = "最后更新时间", IsNullable = true, ColumnDataType = "DateTime")]        public DateTime LastUpdateTime { get; set; } = DateTime.Now;        #region 动态获取、设置StoreVal值       /// <summary>       /// Converts a given value to its string representation and determines its storage data type.       /// </summary>       /// <remarks>If the value is an enumerable of strings or integers, it is serialized as a JSON array.       /// For other class types not explicitly handled, the value is serialized as a JSON object. Date and time values       /// are formatted using the round-trip format specifier ("O").</remarks>       /// <param name="value">The value to convert. Can be null or an instance of a supported type such as string, numeric types, boolean,       /// DateTime, DateOnly, TimeOnly, Guid, or enumerable collections of strings or integers.</param>       /// <returns>A tuple containing the string representation of the value and a string indicating the data type for storage.       /// If the input is null, the Value is null and the DataType is "null".</returns>        private static (string? Value, string DataType) ConvertToStorage(object? value)        {            if (value == null) return (null, "null");            return value switch            {                string s => (s, "string"),                int i => (i.ToString(), "int"),                long l => (l.ToString(), "long"),                decimal d => (d.ToString(), "decimal"),                double d => (d.ToString(), "double"),                float f => (f.ToString(), "float"),                bool b => (b.ToString(), "bool"),                DateTime dt => (dt.ToString("O"), "datetime"),                DateOnly date => (date.ToString("O"), "date"),                TimeOnly time => (time.ToString("O"), "time"),                Guid guid => (guid.ToString(), "guid"),                IEnumerable<string> list => (JsonSerializer.Serialize(list), "string[]"),                IEnumerable<int> list => (JsonSerializer.Serialize(list), "int[]"),                _ when value.GetType().IsClass => (JsonSerializer.Serialize(value), "object"),                _ => (value.ToString(), "string")            };        }        /// <summary>        /// Converts a string representation of a value from storage to its corresponding .NET type based on the        /// specified data type.        /// </summary>        /// <remarks>If the specified data type is not recognized, the original string value is returned.        /// For array and object types, the method attempts to deserialize the string as JSON. If conversion fails for        /// numeric, boolean, or date/time types, the method returns null.</remarks>        /// <param name="value">The string value to convert. Can be null or empty, in which case the method returns null.</param>        /// <param name="dataType">The name of the target data type. Supported values include "string", "int", "long", "decimal", "double",        /// "float", "bool", "datetime", "date", "time", "guid", "string[]", "int[]", and "object". The comparison is        /// case-insensitive.</param>        /// <returns>An object representing the converted value in the specified .NET type, or null if the input is null, empty,        /// or cannot be converted.</returns>        private static object? ConvertFromStorage(string? value, string dataType)        {            if (string.IsNullOrEmpty(value)) return null;            return dataType?.ToLower() switch            {                "string" => value,                "int" => int.TryParse(value, out var result) ? result : null,                "long" => long.TryParse(value, out var result) ? result : null,                "decimal" => decimal.TryParse(value, out var result) ? result : null,                "double" => double.TryParse(value, out var result) ? result : null,                "float" => float.TryParse(value, out var result) ? result : null,                "bool" => bool.TryParse(value, out var result) ? result : null,                "datetime" => DateTime.TryParse(value, out var result) ? result : null,                "date" => DateOnly.TryParse(value, out var result) ? result : null,                "time" => TimeOnly.TryParse(value, out var result) ? result : null,                "guid" => Guid.TryParse(value, out var result) ? result : null,                "string[]" => JsonSerializer.Deserialize<string[]>(value),                "int[]" => JsonSerializer.Deserialize<int[]>(value),                "object" => JsonSerializer.Deserialize<JsonElement>(value),                "null" => null,                _ => value            };        }        [SugarColumn(IsIgnore = true)]        public List<string> TypedFileNameValue        {            get            {                if (!string.IsNullOrEmpty(AttachUrl))                {                    string rootRrl = "http://132.232.92.186:24/Office/";                    var result = JsonSerializer.Deserialize<List<string>>(AttachUrl);                    for (int i = 0; i < result.Count; i++)                    {                        result[i] = $"{rootRrl}{result[i]}";                    }                    return result;                }                return new List<string>();            }            set            {                if (value == null || value.Count < 1)                {                    AttachUrl = "";                }                else                {                    var options = new JsonSerializerOptions                    {                        Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,                        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,                        WriteIndented = true                    };                    AttachUrl = JsonSerializer.Serialize(value, options);                }            }        }        [SugarColumn(IsIgnore = true)]        public object? TypedValue        {            get => ConvertFromStorage(StoreVal, DataType);            set            {                var (storageValue, dataType) = ConvertToStorage(value);                StoreVal = storageValue;                DataType = dataType;            }        }        [SugarColumn(IsIgnore = true)]        public string? StringValue        {            get => DataType == "string" ? StoreVal : null;            set => (StoreVal, DataType) = (value, "string");        }        [SugarColumn(IsIgnore = true)]        public int? IntValue        {            get => DataType == "int" && int.TryParse(StoreVal, out var result) ? result : null;            set => (StoreVal, DataType) = (value?.ToString(), "int");        }        [SugarColumn(IsIgnore = true)]        public decimal? DecimalValue        {            get => DataType == "decimal" && decimal.TryParse(StoreVal, out var result) ? result : null;            set => (StoreVal, DataType) = (value?.ToString(), "decimal");        }        [SugarColumn(IsIgnore = true)]        public bool? BooleanValue        {            get => DataType == "bool" && bool.TryParse(StoreVal, out var result) ? result : null;            set => (StoreVal, DataType) = (value?.ToString(), "bool");        }        [SugarColumn(IsIgnore = true)]        public DateTime? DateTimeValue        {            get => DataType == "datetime" && DateTime.TryParse(StoreVal, out var result) ? result : null;            set => (StoreVal, DataType) = (value?.ToString("O"), "datetime");        }        #endregion        public Grp_VisaProcessSteps() { }        /// <summary>        /// 流程步骤初始化        /// </summary>        /// <param name="groupId"></param>        /// <param name="createUserId"></param>        /// <returns></returns>        public static List<Grp_VisaProcessSteps> StepsInit(int groupId,int createUserId)        {            return new List<Grp_VisaProcessSteps>() {                new(){ GroupId = groupId, Step = 1, DataType = "string", CreateUserId = createUserId, LastUpdateUserId = createUserId }, //第一步:签证启动日(团组信息操作里面打勾确认出团)                new(){ GroupId = groupId, Step = 2, DataType = "string", CreateUserId = createUserId, LastUpdateUserId = createUserId }, //第二步:分配工作(从倒退表里-出批件、护照办理取时间)                new(){ GroupId = groupId, Step = 3, DataType = "string", CreateUserId = createUserId, LastUpdateUserId = createUserId }, //第三步:送外办时间(从倒退表里-送签签证取时间)                new(){ GroupId = groupId, Step = 4, DataType = "string", CreateUserId = createUserId, LastUpdateUserId = createUserId }, //第四步:读取预计出签时间(从签证费用标准-签证时间工作日取时间,送外办时间+签证时间(工作日))                new(){ GroupId = groupId, Step = 5, DataType = "string", CreateUserId = createUserId, LastUpdateUserId = createUserId }, //第五步:实际出签时间(手动填写) 附件                new(){ GroupId = groupId, Step = 6, DataType = "bool", CreateUserId = createUserId, LastUpdateUserId = createUserId }, //第六步:是否需要开出境证明 (否,是) 附件                new(){ GroupId = groupId, Step = 7, DataType = "string[]", CreateUserId = createUserId, LastUpdateUserId = createUserId }, //第七步:是否需要办理电子入境卡手续(否,是) -> 如果是,系统生成附件(个人信息资料+机票航班信息+酒店信息)【在出发前三天内填写,取具体的日期】                new(){ GroupId = groupId, Step = 8, DataType = "string", CreateUserId = createUserId, LastUpdateUserId = createUserId }, //第八步:确认完成操作 (确认完成操作后,不可更改该流程数据)            };        }    }    /// <summary>    /// 签证流程步骤操作日志    /// </summary>    [SugarTable(tableName: "Grp_VisaProcessSteps_Log", TableDescription = "签证流程步骤操作日志")]    public class Grp_VisaProcessSteps_Log : EntityBase    {        /// <summary>        /// 步骤记录ID        /// </summary>        [SugarColumn(ColumnName = "StepId", ColumnDescription = "步骤记录ID", IsNullable = false, ColumnDataType = "int")]        public int StepId { get; set; }        /// <summary>        /// 团组Id        /// </summary>        [SugarColumn(ColumnName = "GroupId", ColumnDescription = "团组Id", IsNullable = true, ColumnDataType = "int")]        public int GroupId { get; set; }        /// <summary>        /// 步骤        /// </summary>        [SugarColumn(ColumnName = "Step", ColumnDescription = "步骤", IsNullable = true, ColumnDataType = "int")]        public int Step { get; set; }        /// <summary>        /// 操作类型(Create, Update, Delete, Complete等)        /// </summary>        [SugarColumn(ColumnName = "OperationType", ColumnDescription = "操作类型", IsNullable = false, ColumnDataType = "varchar(50)")]        public string OperationType { get; set; }        /// <summary>        /// 操作描述        /// </summary>        [SugarColumn(ColumnName = "OperationDescription", ColumnDescription = "操作描述", IsNullable = true, ColumnDataType = "varchar(500)")]        public string OperationDescription { get; set; }        /// <summary>        /// 变更前的数据(JSON格式)        /// </summary>        [SugarColumn(ColumnName = "BeforeData", ColumnDescription = "变更前数据", IsNullable = true, ColumnDataType = "nvarchar(max)")]        public string BeforeData { get; set; }        /// <summary>        /// 变更后的数据(JSON格式)        /// </summary>        [SugarColumn(ColumnName = "AfterData", ColumnDescription = "变更后数据", IsNullable = true, ColumnDataType = "nvarchar(max)")]        public string AfterData { get; set; }        /// <summary>        /// 变更的字段列表(逗号分隔)        /// </summary>        [SugarColumn(ColumnName = "ChangedFields", ColumnDescription = "变更字段", IsNullable = true, ColumnDataType = "varchar(500)")]        public string ChangedFields { get; set; }    }    public class VisaProcessStepsLogView    {        /// <summary>        /// 步骤记录ID        /// </summary>        public int StepId { get; set; }        /// <summary>        /// 团组Id        /// </summary>        public int GroupId { get; set; }        /// <summary>        /// 步骤        /// </summary>        public int Step { get; set; }        /// <summary>        /// 操作类型(Create, Update, Delete, Complete等)        /// </summary>        public string OperationType { get; set; }        /// <summary>        /// 操作描述        /// </summary>        public string OperationDescription { get; set; }        ///// <summary>        ///// 变更前的数据(JSON格式)        ///// </summary>        //public string BeforeData { get; set; }        ///// <summary>        ///// 变更后的数据(JSON格式)        ///// </summary>        //public string AfterData { get; set; }        ///// <summary>        ///// 变更的字段列表(逗号分隔)        ///// </summary>        //public string ChangedFields { get; set; }        /// <summary>        /// 操作人姓名        /// </summary>        public string Operator { get; set; }        /// <summary>        /// 操作时间        /// </summary>        public DateTime OperationTime { get; set; }    }}
 |