Compare commits
43
Commits
8845fb6521
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0c94f3eac | ||
|
|
9edbe83376 | ||
|
|
8019b24b61 | ||
|
|
5875ffe671 | ||
|
|
6d41f52de5 | ||
|
|
25d481d7d6 | ||
|
|
aa0e7c27e5 | ||
|
|
145a47fa8d | ||
|
|
8f82da94b7 | ||
|
|
8b0db6a4e6 | ||
|
|
758735fefc | ||
|
|
ef46c30ed3 | ||
|
|
4340dd25a1 | ||
|
|
3470ce9229 | ||
|
|
6f580ff8eb | ||
|
|
b5ed6a3b1c | ||
|
|
7f269c8b04 | ||
|
|
c12e1b5d65 | ||
|
|
bc90b17961 | ||
|
|
3514cf53f8 | ||
|
|
c07369c297 | ||
|
|
aaebbb9104 | ||
|
|
647f2b75c9 | ||
|
|
0a2ba8bb1a | ||
|
|
61c4e0f977 | ||
|
|
a37c40a2ef | ||
|
|
a23984c9f5 | ||
|
|
57402e0dda | ||
|
|
1c5b9ed3c8 | ||
|
|
76b57c5717 | ||
|
|
01055762ca | ||
|
|
3934088e43 | ||
|
|
3f567cb481 | ||
|
|
eb8a48c642 | ||
|
|
9203788e1d | ||
|
|
16929a2ce0 | ||
|
|
e3317793fe | ||
|
|
54bbfe2fe4 | ||
|
|
3b0c316928 | ||
|
|
26d190afa1 | ||
|
|
3927fd21b5 | ||
|
|
b2ea31de40 | ||
|
|
e94a8bbfd2 |
@@ -361,3 +361,4 @@ MigrationBackup/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
/LMS.service/.idea/.idea.LMS.service/.idea
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Common.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class NotEmptyAttribute : ValidationAttribute
|
||||
{
|
||||
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
|
||||
{
|
||||
if (value is string str && string.IsNullOrWhiteSpace(str))
|
||||
{
|
||||
return new ValidationResult(ErrorMessage ?? "字段不能为空");
|
||||
}
|
||||
return ValidationResult.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using LMS.Common.Enums;
|
||||
|
||||
namespace LMS.Common.Dictionary;
|
||||
|
||||
public class AllOptions
|
||||
{
|
||||
|
||||
public static class AllOptionKey
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取所有的 Option
|
||||
/// </summary>
|
||||
public const string All = "all";
|
||||
|
||||
/// <summary>
|
||||
/// 获取TTS相关的 Option
|
||||
/// </summary>
|
||||
public const string TTS = "tts";
|
||||
|
||||
/// <summary>
|
||||
/// 获取软件相关的 Option
|
||||
/// </summary>
|
||||
public const string Software = "software";
|
||||
|
||||
/// <summary>
|
||||
/// 软件试用相关 Option
|
||||
/// </summary>
|
||||
public const string Trial = "trial";
|
||||
|
||||
/// <summary>
|
||||
/// 出图相关的 Option
|
||||
/// </summary>
|
||||
public const string Image = "image";
|
||||
|
||||
/// <summary>
|
||||
/// 邮件设置相关 Option
|
||||
/// </summary>
|
||||
public const string MailSetting = "mailSetting";
|
||||
|
||||
/// <summary>
|
||||
/// 重置免费次数相关的 Option
|
||||
/// </summary>
|
||||
public const string ResetFreeCount = "resetFreeCount";
|
||||
}
|
||||
|
||||
public static readonly Dictionary<string, List<string>> AllOptionsRequestQuery = new()
|
||||
{
|
||||
{ AllOptionKey.All, [] },
|
||||
{ AllOptionKey.TTS, ["EdgeTTsRoles"] },
|
||||
{ AllOptionKey.Software, ["LaitoolHomePage", "LaitoolNotice", "LaitoolUpdateContent","LaitoolVersion"]},
|
||||
{ AllOptionKey.Trial , ["LaiToolTrialDays"] },
|
||||
{ AllOptionKey.Image, [OptionKeyName.LaitoolFluxApiModelList] },
|
||||
{ AllOptionKey.MailSetting , [OptionKeyName.SMTPMailSetting] },
|
||||
{ AllOptionKey.ResetFreeCount, [OptionKeyName.ResetFreeCountSetting] }
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using LMS.Common.Enums;
|
||||
|
||||
namespace LMS.Common.Dictionary;
|
||||
|
||||
public class SimpleOptions
|
||||
{
|
||||
|
||||
public static class SimpleOptionKey
|
||||
{
|
||||
/// <summary>
|
||||
/// TTS的角色Option
|
||||
/// </summary>
|
||||
public const string Ttsrole = "ttsrole";
|
||||
|
||||
/// <summary>
|
||||
/// LaiTool信息相关的配置
|
||||
/// </summary>
|
||||
public const string Laitoolinfo = "laitoolinfo";
|
||||
|
||||
/// <summary>
|
||||
/// LaiTool FluxAPI对应的模型信息
|
||||
/// </summary>
|
||||
public const string LaitoolFluxApiModelList = "LaitoolFluxApiModelList";
|
||||
|
||||
/// <summary>
|
||||
/// 是否开启邮箱信息
|
||||
/// </summary>
|
||||
public const string EnableMailService = "EnableMailService";
|
||||
}
|
||||
|
||||
public static readonly Dictionary<string, List<string>> SimpleOptionsRequestQuery = new()
|
||||
{
|
||||
{ SimpleOptionKey.Ttsrole, ["EdgeTTsRoles"] },
|
||||
{ SimpleOptionKey.Laitoolinfo, ["LaitoolHomePage", "LaitoolNotice", "LaitoolUpdateContent", "LaitoolVersion"] },
|
||||
{ SimpleOptionKey.LaitoolFluxApiModelList, [OptionKeyName.LaitoolFluxApiModelList] },
|
||||
{ SimpleOptionKey.EnableMailService, [OptionKeyName.EnableMailService]}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using LMS.Common.Attributes;
|
||||
|
||||
namespace LMS.Common.Enums
|
||||
{
|
||||
public enum DataInfoTypeEnum
|
||||
{
|
||||
[Description("Discord")]
|
||||
Discord = 0,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace LMS.Common.Enums
|
||||
{
|
||||
public enum MachineAuthorizationEnum
|
||||
{
|
||||
[Description("NanFengAI")]
|
||||
NanFengAI = 0,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 授权使用类型,目前是专业和基础
|
||||
/// </summary>
|
||||
public enum MachineAuthorizationUseTypeEnum
|
||||
{
|
||||
[Description("基础")]
|
||||
Basic = 0,
|
||||
[Description("专业")]
|
||||
Professional = 1
|
||||
}
|
||||
}
|
||||
@@ -21,11 +21,12 @@ namespace LMS.Common.Enums
|
||||
/// </summary>
|
||||
public enum MachineStatus
|
||||
{
|
||||
[Description("激活")]
|
||||
Active = 1,
|
||||
|
||||
[Description("冻结")]
|
||||
Frozen = 0
|
||||
Frozen = 0,
|
||||
|
||||
[Description("激活")]
|
||||
Active = 1
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
namespace LMS.Common.Enums;
|
||||
|
||||
public enum OptionTypeEnum
|
||||
{
|
||||
String = 1,
|
||||
JSON = 2,
|
||||
Number = 3,
|
||||
Boolean = 4
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// option的分类
|
||||
/// </summary>
|
||||
public enum OptionCategory
|
||||
{
|
||||
System = 1,
|
||||
LaiTool = 2,
|
||||
NanFengAI = 3,
|
||||
}
|
||||
|
||||
public static class OptionKeyName
|
||||
{
|
||||
/// <summary>
|
||||
/// LaiTool Flux API 模型列表的Option Key
|
||||
/// </summary>
|
||||
public const string LaitoolFluxApiModelList = "LaitoolFluxApiModelList";
|
||||
|
||||
/// <summary>
|
||||
/// SMTP的邮件设置
|
||||
/// </summary>
|
||||
public const string SMTPMailSetting = "SMTPMailSetting";
|
||||
|
||||
/// <summary>
|
||||
/// 是否开启邮箱服务
|
||||
/// </summary>
|
||||
public const string EnableMailService = "EnableMailService";
|
||||
|
||||
/// <summary>
|
||||
/// 重置用户免费次数的setting
|
||||
/// </summary>
|
||||
public const string ResetFreeCountSetting = "ResetFreeCountSetting";
|
||||
}
|
||||
@@ -2,14 +2,6 @@
|
||||
{
|
||||
public class PromptEnum
|
||||
{
|
||||
public enum PromptType
|
||||
{
|
||||
/// <summary>
|
||||
/// 开头提示词
|
||||
/// </summary>
|
||||
StartPrompt = 0,
|
||||
}
|
||||
|
||||
public class PromptStatus
|
||||
{
|
||||
/// <summary>
|
||||
@@ -21,6 +13,15 @@
|
||||
///提示词状态:禁用
|
||||
/// </summary>
|
||||
public const string Disable = "disable";
|
||||
|
||||
/// <summary>
|
||||
/// 所有有效的提示词类型状态
|
||||
/// </summary>
|
||||
public static readonly HashSet<string> ValidStatuses =
|
||||
[
|
||||
Enable,
|
||||
Disable
|
||||
];
|
||||
}
|
||||
|
||||
public class PromptTypeStatus
|
||||
@@ -38,11 +39,11 @@
|
||||
/// <summary>
|
||||
/// 所有有效的提示词类型状态
|
||||
/// </summary>
|
||||
public static readonly HashSet<string> ValidStatuses = new HashSet<string>
|
||||
{
|
||||
public static readonly HashSet<string> ValidStatuses =
|
||||
[
|
||||
Enable,
|
||||
Disable
|
||||
};
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,11 @@ namespace LMS.Common.Enums
|
||||
[Description("无效的邀请码")]
|
||||
InvalidAffiliateCode = 1014,
|
||||
|
||||
// 无效token
|
||||
[Result("无效token")]
|
||||
[Description("无效token")]
|
||||
InvalidToken = 1015,
|
||||
|
||||
#endregion
|
||||
|
||||
#region Machine 操作失败
|
||||
@@ -141,6 +146,10 @@ namespace LMS.Common.Enums
|
||||
[Result(ResponseString.InvalidOptions)]
|
||||
[Description(ResponseString.InvalidOptions)]
|
||||
InvalidOptions = 5002,
|
||||
|
||||
[Result(ResponseString.IdDateNotFound)]
|
||||
[Description(ResponseString.IdDateNotFound)]
|
||||
IdDateNotFound = 5003,
|
||||
#endregion
|
||||
|
||||
#region 提示词操作失败
|
||||
@@ -193,6 +202,13 @@ namespace LMS.Common.Enums
|
||||
RoleHasUser = 9004,
|
||||
|
||||
#endregion
|
||||
|
||||
#region 配置项操作失败
|
||||
|
||||
[Result(ResponseString.DataNotExist)]
|
||||
[Description("没有找到指定的配置项")]
|
||||
FindOptionsFail = 10001,
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace LMS.Common.Enums
|
||||
{
|
||||
public class SoftwareControlEnum
|
||||
{
|
||||
public enum SoftwareControlValidityEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 0
|
||||
/// </summary>
|
||||
Zero = 0,
|
||||
/// <summary>
|
||||
/// 一个月
|
||||
/// </summary>
|
||||
Thirty = 30,
|
||||
/// <summary>
|
||||
/// 三个月
|
||||
/// </summary>
|
||||
Ninety = 90,
|
||||
|
||||
/// <summary>
|
||||
/// 六个月
|
||||
/// </summary>
|
||||
OneHundredAndEighty = 180,
|
||||
/// <summary>
|
||||
/// 一年
|
||||
/// </summary>
|
||||
ThreeHundredAndSixtyFive = 365,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
namespace LMS.Common.Extensions
|
||||
{
|
||||
public class BeijingTimeExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取北京时间,将时区转换为北京时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static DateTime GetBeijingTime()
|
||||
{
|
||||
return TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow,
|
||||
TimeZoneInfo.FindSystemTimeZoneById("China Standard Time"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 智能转换时间为北京时间
|
||||
/// 如果是UTC时间则转换,否则直接返回
|
||||
/// </summary>
|
||||
/// <param name="dateTime">输入的时间</param>
|
||||
/// <returns>北京时间</returns>
|
||||
public static DateTime TransferUtcToBeijingTime(DateTime dateTime)
|
||||
{
|
||||
// 只有UTC时间才需要转换
|
||||
if (dateTime.Kind == DateTimeKind.Utc)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 优先使用系统时区信息
|
||||
return TimeZoneInfo.ConvertTimeFromUtc(dateTime,
|
||||
TimeZoneInfo.FindSystemTimeZoneById("China Standard Time"));
|
||||
}
|
||||
catch (TimeZoneNotFoundException)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Linux系统可能使用这个ID
|
||||
return TimeZoneInfo.ConvertTimeFromUtc(dateTime,
|
||||
TimeZoneInfo.FindSystemTimeZoneById("Asia/Shanghai"));
|
||||
}
|
||||
catch (TimeZoneNotFoundException)
|
||||
{
|
||||
// 找不到时区就手动加8小时
|
||||
return dateTime.AddHours(8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 非UTC时间直接返回
|
||||
return dateTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
-1
@@ -1,4 +1,4 @@
|
||||
namespace LMS.Tools.Extensions
|
||||
namespace LMS.Common.Extensions
|
||||
{
|
||||
public class ConvertExtension
|
||||
{
|
||||
@@ -40,5 +40,22 @@
|
||||
|
||||
return 0; // 默认返回0
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串转换为int,默认或者是转换错误返回0
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static int ConvertStringToIntOrDefault(string input)
|
||||
{
|
||||
if (int.TryParse(input, out int result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using LMS.Common.Attributes;
|
||||
using static LMS.Common.Enums.PermissionEnum;
|
||||
|
||||
namespace LMS.Tools
|
||||
namespace LMS.Common.Extensions
|
||||
{
|
||||
public static class EnumExtensions
|
||||
{
|
||||
@@ -6,4 +6,10 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MailKit" Version="4.11.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
namespace LMS.Common.Password
|
||||
{
|
||||
public static class PasswordGenerator
|
||||
{
|
||||
private const string LowercaseChars = "abcdefghijklmnopqrstuvwxyz";
|
||||
private const string UppercaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
private const string NumberChars = "0123456789";
|
||||
private const string SpecialChars = "@$!%*?.&";
|
||||
private const string AllChars = LowercaseChars + UppercaseChars + NumberChars + SpecialChars;
|
||||
|
||||
/// <summary>
|
||||
/// 生成指定长度的随机密码
|
||||
/// </summary>
|
||||
/// <param name="length">密码长度</param>
|
||||
/// <returns>随机生成的密码</returns>
|
||||
public static string GeneratePassword(int length)
|
||||
{
|
||||
if (length < 4)
|
||||
{
|
||||
throw new ArgumentException("密码长度必须至少为4个字符", nameof(length));
|
||||
}
|
||||
|
||||
// 使用加密安全的随机数生成器
|
||||
using var rng = RandomNumberGenerator.Create();
|
||||
// 确保密码包含至少一个小写字母、一个大写字母、一个数字和一个特殊字符
|
||||
var password = new StringBuilder();
|
||||
|
||||
// 添加每种类型的至少一个字符
|
||||
password.Append(GetRandomChar(LowercaseChars, rng));
|
||||
password.Append(GetRandomChar(UppercaseChars, rng));
|
||||
password.Append(GetRandomChar(NumberChars, rng));
|
||||
password.Append(GetRandomChar(SpecialChars, rng));
|
||||
|
||||
// 添加剩余的随机字符
|
||||
for (int i = 4; i < length; i++)
|
||||
{
|
||||
password.Append(GetRandomChar(AllChars, rng));
|
||||
}
|
||||
|
||||
// 打乱字符顺序
|
||||
return ShuffleString(password.ToString(), rng);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从指定字符集中获取一个随机字符
|
||||
/// </summary>
|
||||
private static char GetRandomChar(string chars, RandomNumberGenerator rng)
|
||||
{
|
||||
byte[] data = new byte[1];
|
||||
rng.GetBytes(data);
|
||||
return chars[data[0] % chars.Length];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打乱字符串中字符的顺序
|
||||
/// </summary>
|
||||
private static string ShuffleString(string input, RandomNumberGenerator rng)
|
||||
{
|
||||
char[] array = input.ToCharArray();
|
||||
int n = array.Length;
|
||||
|
||||
while (n > 1)
|
||||
{
|
||||
byte[] box = new byte[1];
|
||||
rng.GetBytes(box);
|
||||
int k = box[0] % n;
|
||||
n--;
|
||||
char temp = array[n];
|
||||
array[n] = array[k];
|
||||
array[k] = temp;
|
||||
}
|
||||
|
||||
return new string(array);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
namespace LMS.Common.Templates
|
||||
{
|
||||
public class EmailTemplateService()
|
||||
{
|
||||
/// <summary>
|
||||
/// 注册邮件模板
|
||||
/// </summary>
|
||||
public const string RegisterHtmlTemplates = """
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<h1>LMS注册验证码</h1>
|
||||
<p>您好,</p>
|
||||
<p>您的验证码是 <strong>{RegisterCode}</strong></p>
|
||||
<p>该验证码有效期为 10 分钟,如果不是您本人操作,请忽略此邮件。</p>
|
||||
</body>
|
||||
</html>
|
||||
""";
|
||||
|
||||
public const string ResetPasswordHtmlTemplates = """
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<h1>LMS重置密码验证码</h1>
|
||||
<p>您好,</p>
|
||||
<p>您的验证码是 <strong>{ResetPasswordCode}</strong></p>
|
||||
<p>该验证码有效期为 10 分钟,如果不是您本人操作,请忽略此邮件。</p>
|
||||
</body>
|
||||
</html>
|
||||
""";
|
||||
|
||||
public const string ResetpasswordSuccessMail = """
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<h1>LMS重置密码成功</h1>
|
||||
<p>您好,</p>
|
||||
<p>您的重置密码操作已经成功!</p>
|
||||
<p>您的新密码是 <strong>{NewPassword}</strong></p>
|
||||
</body>
|
||||
</html>
|
||||
""";
|
||||
|
||||
/// <summary>
|
||||
/// 替换模板的占位符
|
||||
/// </summary>
|
||||
/// <param name="template"></param>
|
||||
/// <param name="parameters"></param>
|
||||
/// <returns></returns>
|
||||
public static string ReplaceTemplate(string template, Dictionary<string, string> parameters)
|
||||
{
|
||||
// 替换占位符
|
||||
foreach (var param in parameters)
|
||||
{
|
||||
template = template.Replace($"{{{param.Key}}}", param.Value);
|
||||
}
|
||||
return template;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
|
||||
|
||||
using LMS.Repository.DB;
|
||||
using LMS.Repository.MJPackage;
|
||||
using LMS.Repository.Models.DB;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
//using Newtonsoft.Json;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace LMS.DAO
|
||||
@@ -20,6 +23,10 @@ namespace LMS.DAO
|
||||
|
||||
public DbSet<PermissionType> PermissionType { get; set; }
|
||||
|
||||
public DbSet<PromptType> PromptType { get; set; }
|
||||
|
||||
public DbSet<Prompt> Prompt { get; set; }
|
||||
|
||||
public DbSet<Machine> Machine { get; set; }
|
||||
|
||||
public DbSet<RefreshTokens> RefreshTokens { get; set; }
|
||||
@@ -28,6 +35,26 @@ namespace LMS.DAO
|
||||
|
||||
public DbSet<RsaKeys> RsaKeys { get; set; }
|
||||
|
||||
public DbSet<Options> Options { get; set; }
|
||||
|
||||
public DbSet<Software> Software { get; set; }
|
||||
|
||||
public DbSet<UserSoftware> UserSoftware { get; set; }
|
||||
|
||||
public DbSet<SoftwareControl> SoftwareControl { get; set; }
|
||||
|
||||
public DbSet<MachineAuthorization> MachineAuthorization { get; set; }
|
||||
|
||||
public DbSet<DataInfo> DataInfo { get; set; }
|
||||
|
||||
public DbSet<MJApiTokens> MJApiTokens { get; set; }
|
||||
|
||||
public DbSet<MJApiTokenUsage> MJApiTokenUsage { get; set; }
|
||||
|
||||
public DbSet<MJApiTasks> MJApiTasks { get; set; }
|
||||
|
||||
public DbSet<FileUploads> FileUploads { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
@@ -40,7 +67,63 @@ namespace LMS.DAO
|
||||
v => string.IsNullOrEmpty(v) || v == "[]"
|
||||
? new List<string>() // 如果存储的是空字符串或空数组,则返回空列表
|
||||
: JsonSerializer.Deserialize<List<string>>(v, (JsonSerializerOptions?)null) ?? new List<string>()
|
||||
).Metadata.SetValueComparer(
|
||||
new ValueComparer<List<string>>(
|
||||
// 比较两个集合是否相等
|
||||
(c1, c2) => c1 != null && c2 != null && c1.SequenceEqual(c2),
|
||||
// 计算集合的哈希码 - 这里修复了问题
|
||||
c => c == null ? 0 : c.Aggregate(0, (a, v) => HashCode.Combine(a, v != null ? v.GetHashCode() : 0)),
|
||||
// 创建集合的副本
|
||||
c => c == null ? null : c.ToList()
|
||||
)
|
||||
);
|
||||
modelBuilder.Entity<UserSoftware>()
|
||||
.HasKey(us => new { us.UserId, us.SoftwareId });
|
||||
|
||||
// Options表的RoleIds字段使用JSON格式存储
|
||||
modelBuilder.Entity<Options>(entity =>
|
||||
{
|
||||
entity.Property(e => e.RoleIds)
|
||||
.HasConversion(
|
||||
v => Newtonsoft.Json.JsonConvert.SerializeObject(v), // 将 List<int> 序列化为 JSON 字符串
|
||||
v => Newtonsoft.Json.JsonConvert.DeserializeObject<List<long>>(v ?? "[]") ?? new List<long>() // 反序列化
|
||||
)
|
||||
.HasColumnType("json"); // 指定MySQL字段类型为JSON
|
||||
});
|
||||
|
||||
modelBuilder.Entity<MJApiTokens>(entity =>
|
||||
{
|
||||
entity.ToTable("MJApiTokens");
|
||||
entity.Property(e => e.Token).IsRequired().HasMaxLength(64);
|
||||
entity.Property(e => e.DailyLimit).HasDefaultValue(0);
|
||||
entity.Property(e => e.TotalLimit).HasDefaultValue(0);
|
||||
entity.Property(e => e.ConcurrencyLimit).HasDefaultValue(1);
|
||||
entity.Property(e => e.CreatedAt).HasDefaultValueSql("CURRENT_TIMESTAMP");
|
||||
|
||||
entity.HasIndex(e => e.Token).IsUnique();
|
||||
entity.HasIndex(e => e.ExpiresAt);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<MJApiTokenUsage>(entity =>
|
||||
{
|
||||
entity.ToTable("MJApiTokenUsage");
|
||||
entity.HasKey(e => new { e.TokenId, e.Date });
|
||||
|
||||
entity.HasOne<MJApiTokens>()
|
||||
.WithMany()
|
||||
.HasForeignKey(e => e.TokenId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<FileUploads>(entity =>
|
||||
{
|
||||
entity.HasIndex(e => e.UserId);
|
||||
entity.HasIndex(e => e.FileKey);
|
||||
entity.HasIndex(e => e.UploadTime);
|
||||
|
||||
entity.Property(e => e.CreatedAt).HasDefaultValueSql("GETDATE()");
|
||||
entity.Property(e => e.UploadTime).HasDefaultValueSql("GETDATE()");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
|
||||
<PackageReference Include="OneOf" Version="3.0.271" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
|
||||
</ItemGroup>
|
||||
@@ -15,7 +16,6 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\LMS.Common\LMS.Common.csproj" />
|
||||
<ProjectReference Include="..\LMS.Repository\LMS.Repository.csproj" />
|
||||
<ProjectReference Include="..\LMS.Tools\LMS.Tools.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
using LMS.Repository.DB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LMS.DAO.OptionDAO
|
||||
{
|
||||
public class OptionGlobalDAO(ApplicationDbContext dbContext)
|
||||
{
|
||||
private readonly ApplicationDbContext _dbContext = dbContext;
|
||||
/// <summary>
|
||||
/// 根据配置键查找并返回指定类型的配置值
|
||||
/// </summary>
|
||||
/// <typeparam name="T">返回值类型</typeparam>
|
||||
/// <param name="optionKey">配置键</param>
|
||||
/// <returns>配置值,如果不存在或转换失败则返回默认值</returns>
|
||||
public async Task<T?> FindAndReturnOption<T>(string optionKey)
|
||||
{
|
||||
// 参数验证
|
||||
if (string.IsNullOrWhiteSpace(optionKey))
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
|
||||
var options = await _dbContext.Options
|
||||
.Where(x => x.Key == optionKey)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (options == null) return default;
|
||||
// 直接返回转换结果,GetValueObject内部应该处理null情况
|
||||
return options.GetValueObject<T>() ?? default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查配置是否存在
|
||||
/// </summary>
|
||||
/// <param name="optionKey">配置键</param>
|
||||
/// <returns>是否存在</returns>
|
||||
public async Task<bool> OptionExists(string optionKey)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(optionKey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return await _dbContext.Options
|
||||
.AnyAsync(x => x.Key == optionKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取多个配置
|
||||
/// </summary>
|
||||
/// <param name="optionKeys">配置键列表</param>
|
||||
/// <returns>配置字典</returns>
|
||||
public async Task<Dictionary<string, Options>> GetMultipleOptions(params string[] optionKeys)
|
||||
{
|
||||
if (optionKeys == null || optionKeys.Length == 0)
|
||||
{
|
||||
return new Dictionary<string, Options>();
|
||||
}
|
||||
|
||||
var options = await _dbContext.Options
|
||||
.Where(x => optionKeys.Contains(x.Key))
|
||||
.ToListAsync();
|
||||
|
||||
return options.ToDictionary(x => x.Key, x => x);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,14 @@
|
||||
using LMS.Repository.Models.DB;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LMS.DAO.UserDAO
|
||||
{
|
||||
public class UserBasicDao(UserManager<User> userManager)
|
||||
public class UserBasicDao(UserManager<User> userManager, ApplicationDbContext dbContext)
|
||||
{
|
||||
private readonly UserManager<User> _userManager = userManager;
|
||||
private readonly ApplicationDbContext _dbContext = dbContext;
|
||||
|
||||
/// <summary>
|
||||
/// 检查用户是否存在,通过用户ID
|
||||
/// </summary>
|
||||
@@ -24,6 +22,128 @@ namespace LMS.DAO.UserDAO
|
||||
}
|
||||
return await _userManager.FindByIdAsync(userId.ToString()) != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断传入的数据是不是有管理员权限或者是超级管理员权限
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public async Task<bool> CheckUserIsAdminOrSuperAdmin(long? userId)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
User? user = await _userManager.FindByIdAsync(userId.ToString() ?? "0") ?? throw new Exception("用户不存在");
|
||||
|
||||
bool isAdminOrSuperAdmin = await _userManager.IsInRoleAsync(user, "Admin") || await _userManager.IsInRoleAsync(user, "Super Admin");
|
||||
return isAdminOrSuperAdmin || userId == 4;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查用户是不是超级管理员
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public async Task<bool> CheckUserIsSuperAdmin(long? userId)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
User? user = await _userManager.FindByIdAsync(userId.ToString() ?? "0") ?? throw new Exception("用户不存在");
|
||||
|
||||
bool isSuperAdmin = await _userManager.IsInRoleAsync(user, "Super Admin");
|
||||
return isSuperAdmin || userId == 4;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查用户是不是管理员
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public async Task<bool> CheckUserIsAdmin(long? userId)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
User? user = await _userManager.FindByIdAsync(userId.ToString() ?? "0") ?? throw new Exception("用户不存在");
|
||||
|
||||
bool isSuperAdmin = await _userManager.IsInRoleAsync(user, "Admin");
|
||||
return isSuperAdmin || userId == 4;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查用户是不是代理
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public async Task<bool> CheckUserIsAgent(long? userId)
|
||||
{
|
||||
if (userId == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
User? user = await _userManager.FindByIdAsync(userId.ToString() ?? "0") ?? throw new Exception("用户不存在");
|
||||
|
||||
bool isSuperAdmin = await _userManager.IsInRoleAsync(user, "Agent User");
|
||||
return isSuperAdmin || userId == 4;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断用户是不是指定用户的上级
|
||||
/// </summary>
|
||||
/// <param name="userId">用户ID</param>
|
||||
/// <param name="agentUserId">上级用户ID</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> CheckAgentAndUserMatch(long? userId, long? agentUserId)
|
||||
{
|
||||
if (userId == null || agentUserId == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool isAgent = await CheckUserIsAgent(agentUserId);
|
||||
if (!isAgent)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
User? user = await _userManager.FindByIdAsync(userId.ToString() ?? "0") ?? throw new Exception("用户不存在");
|
||||
if (user == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (user.ParentId != agentUserId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户的所有角色ID
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public async Task<List<long>> GetUserRoleIds(long userId)
|
||||
{
|
||||
// 查找用户,若不存在直接抛异常
|
||||
User user = await _userManager.FindByIdAsync(userId.ToString())
|
||||
?? throw new Exception("用户不存在");
|
||||
|
||||
// 直接查询 UserRoles 表获取所有关联的 RoleId
|
||||
var roleIds = await _dbContext.UserRoles
|
||||
.Where(ur => ur.UserId == user.Id)
|
||||
.Select(ur => ur.RoleId)
|
||||
.ToListAsync();
|
||||
|
||||
return roleIds;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using LMS.Tools.Extensions;
|
||||
using LMS.Common.Extensions;
|
||||
|
||||
namespace LMS.Repository.Models.DB
|
||||
{
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
using LMS.Common.Enums;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Repository.DB
|
||||
{
|
||||
public class DataInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// ID
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required string ID { get; set; }
|
||||
/// <summary>
|
||||
/// 数据的类型
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required DataInfoTypeEnum Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据的字符串
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required string DataString { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime CreatedTime { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Repository.DB;
|
||||
|
||||
public class FileUploads
|
||||
{
|
||||
[Key]
|
||||
public long Id { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(50)]
|
||||
public long UserId { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(255)]
|
||||
public string FileName { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(500)]
|
||||
public string FileKey { get; set; }
|
||||
|
||||
public long FileSize { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(100)]
|
||||
public string ContentType { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(100)]
|
||||
public string Hash { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(1000)]
|
||||
public string QiniuUrl { get; set; }
|
||||
|
||||
public DateTime UploadTime { get; set; }
|
||||
|
||||
[StringLength(20)]
|
||||
public string Status { get; set; } = "active";
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 删除时间 ,默认为最大值,表示未删除
|
||||
/// </summary>
|
||||
public DateTime DeleteTime { get; set; } = DateTime.MaxValue;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using LMS.Repository.MJPackage;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Repository.DB
|
||||
{
|
||||
public class MJApiTasks
|
||||
{
|
||||
[Key]
|
||||
public string TaskId { get; set; }
|
||||
public string Token { get; set; }
|
||||
public long TokenId { get; set; }
|
||||
public DateTime StartTime { get; set; }
|
||||
public DateTime? EndTime { get; set; }
|
||||
public string Status { get; set; }
|
||||
public string ThirdPartyTaskId { get; set; } // 第三方任务ID
|
||||
public string? Properties { get; set; }
|
||||
}
|
||||
|
||||
public class MJApiTaskCollection : MJApiTasks
|
||||
{
|
||||
public long TokenId { get; set; }
|
||||
public string Token { get; set; }
|
||||
}
|
||||
|
||||
public class MJTaskStatus
|
||||
{
|
||||
public const string NOT_START = "NOT_START";
|
||||
|
||||
public const string SUBMITTED = "SUBMITTED";
|
||||
|
||||
public const string IN_PROGRESS = "IN_PROGRESS";
|
||||
|
||||
public const string FAILURE = "FAILURE";
|
||||
|
||||
public const string SUCCESS = "SUCCESS";
|
||||
|
||||
public const string MODAL = "MODAL";
|
||||
|
||||
public const string CANCEL = "CANCEL";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using LMS.Common.Extensions;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Repository.DB
|
||||
{
|
||||
public class MJApiTokenUsage
|
||||
{
|
||||
[Key]
|
||||
public long TokenId { get; set; }
|
||||
|
||||
[Key]
|
||||
public DateTime Date { get; set; }
|
||||
|
||||
public int DailyUsage { get; set; } = 0;
|
||||
|
||||
public int TotalUsage { get; set; } = 0;
|
||||
|
||||
public DateTime LastActivityAt { get; set; } = BeijingTimeExtension.GetBeijingTime();
|
||||
|
||||
public string? HistoryUse { get; set; } = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using LMS.Common.Extensions;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace LMS.Repository.DB
|
||||
{
|
||||
public class MJApiTokens
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public long Id { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(64)]
|
||||
public required string Token { get; set; }
|
||||
[Required]
|
||||
public required string UseToken { get; set; } // 实际使用的Token
|
||||
|
||||
public int DailyLimit { get; set; } = 0;
|
||||
|
||||
public int TotalLimit { get; set; } = 0;
|
||||
|
||||
public int ConcurrencyLimit { get; set; } = 1;
|
||||
|
||||
public DateTime CreatedAt { get; set; } = BeijingTimeExtension.GetBeijingTime();
|
||||
|
||||
public DateTime? ExpiresAt { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using static LMS.Common.Enums.MachineEnum;
|
||||
|
||||
namespace LMS.Repository.Models.DB
|
||||
namespace LMS.Repository.DB
|
||||
{
|
||||
public class Machine
|
||||
{
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
using LMS.Common.Enums;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using static LMS.Common.Enums.SoftwareControlEnum;
|
||||
|
||||
namespace LMS.Repository.DB
|
||||
{
|
||||
public class MachineAuthorization
|
||||
{
|
||||
/// <summary>
|
||||
/// ID
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required string ID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 机器码或者是授权码
|
||||
/// </summary>
|
||||
public string? MachineID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权时间
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required SoftwareControlValidityEnum ExpiryTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权使用状态
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required MachineAuthorizationUseTypeEnum UseType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权软件类型
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required MachineAuthorizationEnum Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权日期
|
||||
/// </summary>
|
||||
[Required]
|
||||
public DateTime AuthorizedDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 过期日期
|
||||
/// </summary>
|
||||
[Required]
|
||||
public DateTime ExpiryDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权码
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required string AuthorizationCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建用户ID
|
||||
/// </summary>
|
||||
public long CreatedUserID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime CreatedDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新用户ID
|
||||
/// </summary>
|
||||
public long UpdatedUserID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
/// </summary>
|
||||
public DateTime UpdatedDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using LMS.Common.Enums;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Repository.DB;
|
||||
|
||||
public class Options
|
||||
{
|
||||
[Key]
|
||||
[Required]
|
||||
public required string Key { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Value of the option,这个值是一个json字符串
|
||||
/// </summary>
|
||||
public string? Value { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
public OptionTypeEnum Type { get; set; } = OptionTypeEnum.String;
|
||||
|
||||
[Required]
|
||||
public OptionCategory Category { get; set; } = OptionCategory.System;
|
||||
|
||||
[Required]
|
||||
public List<long> RoleIds { get; set; } = [];
|
||||
|
||||
public DateTime CreatedTime { get; set; }
|
||||
|
||||
// 写一个字段,映射Value,判断是不是json字符串,是的话就解析成对象
|
||||
public T? GetValueObject<T>()
|
||||
{
|
||||
if (string.IsNullOrEmpty(Value))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
if (Type == OptionTypeEnum.JSON)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<T>(Value ?? "{}");
|
||||
}
|
||||
|
||||
if (Type == OptionTypeEnum.Number)
|
||||
{
|
||||
if (double.TryParse(Value, out double result))
|
||||
{
|
||||
return (T)Convert.ChangeType(result, typeof(T));
|
||||
}
|
||||
return default;
|
||||
}
|
||||
|
||||
return (T)Convert.ChangeType(Value, typeof(T));
|
||||
}
|
||||
|
||||
// 写一个方法,设置Value的值
|
||||
public void SetValueObject<T>(T value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
Value = string.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Type == OptionTypeEnum.JSON)
|
||||
{
|
||||
Value = JsonConvert.SerializeObject(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Value = value.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using LMS.Common.Enums;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text.Json;
|
||||
using static LMS.Common.Enums.PermissionEnum;
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using LMS.Common.Enums;
|
||||
using static LMS.Common.Enums.PermissionEnum;
|
||||
|
||||
namespace LMS.Repository.Models.DB
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace LMS.Repository.Models.DB
|
||||
namespace LMS.Repository.DB
|
||||
{
|
||||
public class Prompt
|
||||
{
|
||||
@@ -45,7 +45,7 @@
|
||||
/// <summary>
|
||||
/// 创建者
|
||||
/// </summary>
|
||||
public string CreateUserId { get; set; }
|
||||
public long CreateUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
@@ -55,7 +55,7 @@
|
||||
/// <summary>
|
||||
/// 更新者
|
||||
/// </summary>
|
||||
public string UpdateUserId { get; set; }
|
||||
public long UpdateUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
|
||||
@@ -1,35 +1,12 @@
|
||||
namespace LMS.Repository.Models.DB
|
||||
using LMS.Repository.DTO.PromptTypeDto;
|
||||
|
||||
namespace LMS.Repository.Models.DB
|
||||
{
|
||||
/// <summary>
|
||||
/// 提示词类型的库
|
||||
/// </summary>
|
||||
public class PromptType
|
||||
public class PromptType : PromptTypeBasic
|
||||
{
|
||||
/// <summary>
|
||||
/// ID
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词类型编码
|
||||
/// </summary>
|
||||
public string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词类型名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词类型描述
|
||||
/// </summary>
|
||||
public string? Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词类型状态
|
||||
/// </summary>
|
||||
public string Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否删除
|
||||
/// </summary>
|
||||
@@ -38,7 +15,7 @@
|
||||
/// <summary>
|
||||
/// 创建用户ID
|
||||
/// </summary>
|
||||
public string CreateUserId { get; set; }
|
||||
public long CreateUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
@@ -48,14 +25,11 @@
|
||||
/// <summary>
|
||||
/// 更新者ID
|
||||
/// </summary>
|
||||
public string UpdateUserId { get; set; }
|
||||
public long UpdateUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
/// </summary>
|
||||
public DateTime UpdateTime { get; set; }
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using LMS.Tools.Extensions;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace LMS.Repository.Models.DB
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using LMS.Tools.Extensions;
|
||||
using LMS.Common.Extensions;
|
||||
|
||||
namespace LMS.Repository.DB
|
||||
{
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
namespace LMS.Repository.DB;
|
||||
|
||||
public class Software
|
||||
{
|
||||
/// <summary>
|
||||
/// ID
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
/// <summary>
|
||||
/// 软件名称
|
||||
/// </summary>
|
||||
public string SoftwareName { get; set; }
|
||||
/// <summary>
|
||||
/// 软件代码
|
||||
/// </summary>
|
||||
public string SoftwareCode { get; set; }
|
||||
/// <summary>
|
||||
/// 创建用户ID
|
||||
/// </summary>
|
||||
public long CreatedUserId { get; set; }
|
||||
/// <summary>
|
||||
/// 更新用户ID
|
||||
/// </summary>
|
||||
public long UpdatedUserId { get; set; }
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime CreatedTime { get; set; }
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
/// </summary>
|
||||
public DateTime UpdatedTime { get; set; }
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
public bool IsUse { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
namespace LMS.Repository.DB;
|
||||
|
||||
public class SoftwareControl
|
||||
{
|
||||
/// <summary>
|
||||
/// ID
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
/// <summary>
|
||||
/// 用户ID
|
||||
/// </summary>
|
||||
public long UserId { get; set; }
|
||||
/// <summary>
|
||||
/// 软件ID
|
||||
/// </summary>
|
||||
public string SoftwareId { get; set; }
|
||||
/// <summary>
|
||||
/// 创建用户ID
|
||||
/// </summary>
|
||||
public long CreatedUserId { get; set; }
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime CreatedTime { get; set; }
|
||||
/// <summary>
|
||||
/// 更新用户ID
|
||||
/// </summary>
|
||||
public long UpdatedUserId { get; set; }
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
/// </summary>
|
||||
public DateTime UpdatedTime { get; set; }
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
/// <summary>
|
||||
/// 到期时间
|
||||
/// </summary>
|
||||
public DateTime? ExpirationTime { get; set; }
|
||||
/// <summary>
|
||||
/// 是否永久
|
||||
/// </summary>
|
||||
public bool IsForever { get; set; }
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using LMS.Repository.User;
|
||||
using LMS.Common.Extensions;
|
||||
using LMS.Repository.User;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
@@ -33,13 +34,13 @@ namespace LMS.Repository.Models.DB
|
||||
public string? Options { get; set; } = "{}";
|
||||
|
||||
[Column(TypeName = "datetime")]
|
||||
public DateTime CreatedDate { get; set; } = DateTime.Now;
|
||||
public DateTime CreatedDate { get; set; } = BeijingTimeExtension.GetBeijingTime();
|
||||
|
||||
[Column(TypeName = "datetime")]
|
||||
public DateTime UpdatedDate { get; set; } = DateTime.Now;
|
||||
public DateTime UpdatedDate { get; set; } = BeijingTimeExtension.GetBeijingTime();
|
||||
|
||||
[Column(TypeName = "datetime")]
|
||||
public DateTime LastLoginDate { get; set; } = DateTime.Now;
|
||||
public DateTime LastLoginDate { get; set; } = BeijingTimeExtension.GetBeijingTime();
|
||||
|
||||
public string? LastLoginIp { get; set; } = "";
|
||||
|
||||
@@ -55,6 +56,16 @@ namespace LMS.Repository.Models.DB
|
||||
/// </summary>
|
||||
public string AffiliateCode { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 用户微信号
|
||||
/// </summary>
|
||||
public string? WXNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string? Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 实际使用的Options
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace LMS.Repository.DB;
|
||||
|
||||
public class UserSoftware
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户ID
|
||||
/// </summary>
|
||||
public long UserId { get; set; }
|
||||
/// <summary>
|
||||
/// 软件ID
|
||||
/// </summary>
|
||||
public string SoftwareId { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string MachineId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 软件控制ID
|
||||
/// </summary>
|
||||
public string SoftwareControlId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using LMS.Repository.DB;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Repository.DTO
|
||||
{
|
||||
public class FileUploadDto
|
||||
{
|
||||
public class ByteUploadRequest
|
||||
{
|
||||
//public required string FileBytes { get; set; }
|
||||
/// <summary>
|
||||
/// 文件的base64
|
||||
/// </summary>
|
||||
public required string File { get; set; }
|
||||
public required string FileName { get; set; }
|
||||
public required string ContentType { get; set; }
|
||||
public Dictionary<string, string> Metadata { get; set; } = new();
|
||||
public string? Type { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// URL上传请求
|
||||
/// </summary>
|
||||
public class UrlUploadRequest
|
||||
{
|
||||
[Required]
|
||||
[Url]
|
||||
public required string Url { get; set; }
|
||||
|
||||
[Required]
|
||||
public required string FileName { get; set; }
|
||||
}
|
||||
|
||||
public class UploadResult
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public string Message { get; set; }
|
||||
public string Url { get; set; }
|
||||
public string FileKey { get; set; }
|
||||
public string Hash { get; set; }
|
||||
public long FileId { get; set; }
|
||||
public long FileSize { get; set; }
|
||||
}
|
||||
|
||||
public class FileListResponse
|
||||
{
|
||||
public List<FileUploads> Files { get; set; }
|
||||
public int TotalCount { get; set; }
|
||||
public int Page { get; set; }
|
||||
public int PageSize { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
using LMS.Repository.DTO.UserDto;
|
||||
using LMS.Repository.Models.DB;
|
||||
using LMS.Repository.DB;
|
||||
using LMS.Repository.DTO.UserDto;
|
||||
using LMS.Repository.Machine;
|
||||
|
||||
namespace LMS.Repository.DTO
|
||||
{
|
||||
public class MachineDetailDto : Machine
|
||||
public class MachineDetailDto : MachineModel
|
||||
{
|
||||
public UserBaseDto? CreatedUser { get; set; }
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using static LMS.Common.Enums.MachineEnum;
|
||||
|
||||
namespace LMS.Repository.DTO.MachineResponse
|
||||
namespace LMS.Repository.DTO
|
||||
{
|
||||
public class MachineDto
|
||||
{
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using LMS.Common.Enums;
|
||||
|
||||
namespace LMS.Repository.DTO.OptionDto
|
||||
{
|
||||
public class OptionSimpleDto
|
||||
{
|
||||
public required string Key { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Value of the option,这个值是一个json字符串
|
||||
/// </summary>
|
||||
public string? Value { get; set; } = string.Empty;
|
||||
|
||||
|
||||
public OptionTypeEnum Type { get; set; } = OptionTypeEnum.String;
|
||||
|
||||
public OptionCategory Category { get; set; } = OptionCategory.System;
|
||||
|
||||
public List<string> RoleNames { get; set; } = [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using LMS.Common.Enums;
|
||||
|
||||
namespace LMS.Repository.DTO.OptionDto;
|
||||
|
||||
public class OptionsDto
|
||||
{
|
||||
public required string Key { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Value of the option,这个值是一个json字符串
|
||||
/// </summary>
|
||||
public string? Value { get; set; }
|
||||
|
||||
public OptionTypeEnum Type { get; set; } = OptionTypeEnum.String;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using LMS.Common.Enums;
|
||||
using LMS.Repository.DTO.UserDto;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using static LMS.Common.Enums.SoftwareControlEnum;
|
||||
|
||||
namespace LMS.Repository.DTO.OtherDto
|
||||
{
|
||||
public class MachineAuthorizationDto
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// ID
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required string ID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 机器码或者是授权码
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required string MachineID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 可用时间
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required SoftwareControlValidityEnum ExpiryTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权使用状态
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required MachineAuthorizationUseTypeEnum UseType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权软件类型
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required MachineAuthorizationEnum Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权日期
|
||||
/// </summary>
|
||||
[Required]
|
||||
public DateTime AuthorizedDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 过期日期
|
||||
/// </summary>
|
||||
[Required]
|
||||
public DateTime ExpiryDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权码
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required string AuthorizationCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建用户
|
||||
/// </summary>
|
||||
public UserBaseDto? CreatedUser { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime CreatedDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新用户ID
|
||||
/// </summary>
|
||||
public UserBaseDto? UpdatedUser { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
/// </summary>
|
||||
public DateTime UpdatedDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using LMS.Common.Enums;
|
||||
using static LMS.Common.Enums.SoftwareControlEnum;
|
||||
|
||||
namespace LMS.Repository.DTO.OtherDto
|
||||
{
|
||||
public class MachineAuthorizationStatusDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 机器码
|
||||
/// </summary>
|
||||
public string MachineID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权软件类型
|
||||
/// </summary>
|
||||
public MachineAuthorizationEnum Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权使用状态
|
||||
/// </summary>
|
||||
public MachineAuthorizationUseTypeEnum UseType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权软件类型
|
||||
/// </summary>
|
||||
public SoftwareControlValidityEnum ExpiryTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权日期
|
||||
/// </summary>
|
||||
public DateTime AuthorizedDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 过期日期
|
||||
/// </summary>
|
||||
public DateTime ExpiryDate { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 授权码
|
||||
/// </summary>
|
||||
public string AuthorizationCode { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using LMS.Repository.DB;
|
||||
using LMS.Repository.DTO.PromptTypeDto;
|
||||
using LMS.Repository.DTO.UserDto;
|
||||
|
||||
namespace LMS.Repository.DTO.PromptDto;
|
||||
|
||||
public class PromptDto : Prompt
|
||||
{
|
||||
|
||||
public UserBaseDto CreatedUser { get; set; }
|
||||
|
||||
public UserBaseDto UpdatedUser { get; set; }
|
||||
|
||||
public PromptTypeBasic? PromptType { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace LMS.Repository.DTO.PromptDto;
|
||||
|
||||
public class PromptNameDto
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string PromptTypeId { get; set; }
|
||||
|
||||
public string? Remark { get; set; }
|
||||
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace LMS.Repository.DTO.PromptTypeDto;
|
||||
|
||||
public class PrompTypeNameModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Id { get; set; }
|
||||
|
||||
public string? Remark { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace LMS.Repository.DTO.PromptTypeDto;
|
||||
|
||||
public class PromptTypeBasic
|
||||
{
|
||||
/// <summary>
|
||||
/// ID
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词类型编码
|
||||
/// </summary>
|
||||
public string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词类型名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词类型描述
|
||||
/// </summary>
|
||||
public string? Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词类型状态
|
||||
/// </summary>
|
||||
public string Status { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using LMS.Repository.DTO.UserDto;
|
||||
using LMS.Repository.Models.DB;
|
||||
|
||||
namespace LMS.Repository.DTO.PromptTypeDto
|
||||
{
|
||||
public class PromptTypeDto : PromptType
|
||||
{
|
||||
public UserBaseDto? UpdatedUser { get; set; }
|
||||
|
||||
public UserBaseDto? CreatedUser { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace LMS.Repository.DTO.Software
|
||||
{
|
||||
public class SoftwareBasicDto
|
||||
{
|
||||
public string Id { get; set; } = string.Empty;
|
||||
|
||||
public string SoftwareName { get; set; } = string.Empty;
|
||||
|
||||
public string SoftwareCode { get; set; } = string.Empty;
|
||||
|
||||
public bool IsUse { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using LMS.Repository.DTO.UserDto;
|
||||
|
||||
namespace LMS.Repository.DTO.Software
|
||||
{
|
||||
public class SoftwareCollectionDto
|
||||
{
|
||||
/// <summary>
|
||||
/// ID
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
/// <summary>
|
||||
/// 软件名称
|
||||
/// </summary>
|
||||
public string SoftwareName { get; set; }
|
||||
/// <summary>
|
||||
/// 软件代码
|
||||
/// </summary>
|
||||
public string SoftwareCode { get; set; }
|
||||
/// <summary>
|
||||
/// 创建用户ID
|
||||
/// </summary>
|
||||
public UserBaseDto CreatedUser { get; set; }
|
||||
/// <summary>
|
||||
/// 更新用户ID
|
||||
/// </summary>
|
||||
public UserBaseDto UpdatedUser { get; set; }
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime CreatedTime { get; set; }
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
/// </summary>
|
||||
public DateTime UpdatedTime { get; set; }
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
public bool IsUse { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using LMS.Repository.DTO.UserDto;
|
||||
namespace LMS.Repository.DTO.Software
|
||||
{
|
||||
public class SoftwareControlCollectionDto
|
||||
{
|
||||
/// <summary>
|
||||
/// ID
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
/// <summary>
|
||||
/// 用户ID
|
||||
/// </summary>
|
||||
public UserBaseDto User { get; set; }
|
||||
/// <summary>
|
||||
/// 软件ID
|
||||
/// </summary>
|
||||
public DB.Software Software { get; set; }
|
||||
/// <summary>
|
||||
/// 创建用户ID
|
||||
/// </summary>
|
||||
public UserBaseDto CreatedUser { get; set; }
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime CreatedTime { get; set; }
|
||||
/// <summary>
|
||||
/// 更新用户ID
|
||||
/// </summary>
|
||||
public UserBaseDto UpdatedUser { get; set; }
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
/// </summary>
|
||||
public DateTime UpdatedTime { get; set; }
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
/// <summary>
|
||||
/// 到期时间
|
||||
/// </summary>
|
||||
public DateTime? ExpirationTime { get; set; }
|
||||
/// <summary>
|
||||
/// 是否永久
|
||||
/// </summary>
|
||||
public bool IsForever { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -15,4 +15,11 @@ public class UserBaseDto
|
||||
public string PhoneNumber { get; set; } = string.Empty;
|
||||
|
||||
public string Avatar { get; set; } = string.Empty;
|
||||
|
||||
// 添加隐藏联系信息的方法
|
||||
public void HideContactInfo()
|
||||
{
|
||||
Email = "**********";
|
||||
PhoneNumber = "***********";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,5 +13,7 @@
|
||||
public string LastLoginIp { get; set; } = string.Empty;
|
||||
|
||||
public string LastLoginDevice { get; set; } = string.Empty;
|
||||
|
||||
public string Remark { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,16 @@ namespace LMS.Repository.DTO.UserDto
|
||||
/// </summary>
|
||||
public string AffiliateCode { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 所属用户ID
|
||||
/// </summary>
|
||||
public long ParentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string? Remark { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 放一些操作信息 不能频繁的修改数据库,使用的json格式存放
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
namespace LMS.Repository.FileUpload
|
||||
{
|
||||
public class FileRequestReturn
|
||||
{
|
||||
public class FileMachineRequestReturn
|
||||
{
|
||||
public string MachineId { get; set; }
|
||||
public string FileName { get; set; }
|
||||
public long FileSize { get; set; }
|
||||
public string ContentType { get; set; }
|
||||
|
||||
public string Hash { get; set; }
|
||||
|
||||
public string Url { get; set; }
|
||||
|
||||
public DateTime UploadTime { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
/// <summary>
|
||||
/// 删除时间 ,默认为最大值,表示未不删除
|
||||
/// </summary>
|
||||
public DateTime DeleteTime { get; set; } = DateTime.MaxValue;
|
||||
}
|
||||
|
||||
public class FileUserRequestReturn
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public long UserId { get; set; }
|
||||
public string FileName { get; set; }
|
||||
public long FileSize { get; set; }
|
||||
public string ContentType { get; set; }
|
||||
public string Hash { get; set; }
|
||||
public string Url { get; set; }
|
||||
public DateTime UploadTime { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
/// <summary>
|
||||
/// 删除时间 ,默认为最大值,表示未不删除
|
||||
/// </summary>
|
||||
public DateTime DeleteTime { get; set; } = DateTime.MaxValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace LMS.Repository.FileUpload;
|
||||
public class QiniuSettings
|
||||
{
|
||||
public string AccessKey { get; set; }
|
||||
public string SecretKey { get; set; }
|
||||
public string BucketName { get; set; }
|
||||
public string Domain { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 删除时间 天数 没有值 则不删除
|
||||
/// </summary>
|
||||
public int? DeleteDay { get; set; }
|
||||
}
|
||||
|
||||
public class FileUploadSettings
|
||||
{
|
||||
public long MaxFileSize { get; set; } = 3 * 1024 * 1024; // 5MB
|
||||
public List<string> AllowedContentTypes { get; set; } = new();
|
||||
public int DailyUploadLimit { get; set; } = 5;
|
||||
public int VideoDailyUploadLimit { get; set; } = 50;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Repository.Forward;
|
||||
|
||||
public class ForwardModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 提示词类型ID
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string PromptTypeId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词ID
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string PromptId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// GPT 请求网址
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string GptUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 调用的模型
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string Model { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 机器码
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string MachineId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// API Key
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string ApiKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 处理之前的文案,基础文案
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string Word { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class ForwardModelOpenAI : ForwardModel
|
||||
{
|
||||
[Required]
|
||||
public string OpenAIBodyString { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
namespace LMS.Repository.Forward;
|
||||
|
||||
public class SimpleTransferModel
|
||||
{
|
||||
/// <summary>
|
||||
/// GPT的完整地址
|
||||
/// </summary>
|
||||
public string url { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 对应的API站的使用的APIkey
|
||||
/// </summary>
|
||||
public string APIKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 实际的GPT请求的数据字符串,直接序列化再传递就行
|
||||
/// </summary>
|
||||
public string dataString { get; set; }
|
||||
}
|
||||
|
||||
public class GetTransferModel
|
||||
{
|
||||
/// <summary>
|
||||
/// GPT的完整地址
|
||||
/// </summary>
|
||||
public string url { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 对应的API站的使用的APIkey
|
||||
/// </summary>
|
||||
public string? APIKey { get; set; }
|
||||
}
|
||||
@@ -6,16 +6,13 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Prompt\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="8.0.8" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\LMS.Tools\LMS.Tools.csproj" />
|
||||
<ProjectReference Include="..\LMS.Common\LMS.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Repository.MJPackage
|
||||
{
|
||||
public class AddOrModifyTokenModel
|
||||
{
|
||||
/// <summary>
|
||||
/// token
|
||||
/// </summary>
|
||||
[Required]
|
||||
[StringLength(64)]
|
||||
public required string Token { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 实际使用的Token
|
||||
/// </summary>
|
||||
public required string UseToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 日限制
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required int DailyLimit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总限制
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required int TotalLimit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 并发限制
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required int ConcurrencyLimit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 使用天数
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required int UseDayCount { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
namespace LMS.Repository.MJPackage
|
||||
{
|
||||
public class MJSubmitImageModel
|
||||
{
|
||||
/// <summary>
|
||||
/// bot 类型,mj(默认)或niji
|
||||
/// MID_JOURNEY | 枚举值: NIJI_JOURNEY
|
||||
/// </summary>
|
||||
public string? BotType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词。
|
||||
/// </summary>
|
||||
public string Prompt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 垫图base64数组。
|
||||
/// </summary>
|
||||
public List<string>? Base64Array { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 账号过滤
|
||||
/// </summary>
|
||||
public AccountFilter? AccountFilter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数。
|
||||
/// </summary>
|
||||
public string? State { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 回调地址, 为空时使用全局notifyHook。
|
||||
/// </summary>
|
||||
public string? NotifyHook { get; set; }
|
||||
}
|
||||
|
||||
public class AccountFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// 过滤指定实例的账号
|
||||
/// </summary>
|
||||
public string? InstanceId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 账号模式 RELAX | FAST | TURBO
|
||||
/// </summary>
|
||||
public List<GenerationSpeedMode>? Modes { get; set; } = new List<GenerationSpeedMode>();
|
||||
|
||||
/// <summary>
|
||||
/// 账号是否 remix(Midjourney Remix)
|
||||
/// </summary>
|
||||
public bool? Remix { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 账号是否 remix(Nijiourney Remix)
|
||||
/// </summary>
|
||||
public bool? NijiRemix { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 账号过滤时,remix 自动提交视为账号的 remix 为 false
|
||||
/// </summary>
|
||||
public bool? RemixAutoConsidered { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成速度模式枚举.
|
||||
/// </summary>
|
||||
public enum GenerationSpeedMode
|
||||
{
|
||||
RELAX,
|
||||
FAST,
|
||||
TURBO
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using LMS.Repository.DB;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace LMS.Repository.MJPackage
|
||||
{
|
||||
public class MJTaskCallbackModel
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
public string? Action { get; set; }
|
||||
|
||||
public MJTaskStatus? Status { get; set; }
|
||||
|
||||
public string? Prompt { get; set; }
|
||||
|
||||
public string? PromptEn { get; set; }
|
||||
|
||||
public string? Description { get; set; }
|
||||
|
||||
public long? SubmitTime { get; set; }
|
||||
|
||||
public long? StartTime { get; set; }
|
||||
|
||||
public long? FinishTime { get; set; }
|
||||
|
||||
public string? Progress { get; set; }
|
||||
|
||||
public string? ImageUrl { get; set; }
|
||||
|
||||
public string? FailReason { get; set; }
|
||||
|
||||
public ResponseProperties? Properties { get; set; }
|
||||
}
|
||||
|
||||
public class ResponseProperties
|
||||
{
|
||||
public string? FinalPrompt { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace LMS.Repository.MJPackage
|
||||
{
|
||||
// Models/SyncResult.cs
|
||||
public class SyncResult
|
||||
{
|
||||
public int TotalTokenCount { get; set; }
|
||||
public int ActiveTokenCount { get; set; }
|
||||
public int RecordsUpdated { get; set; }
|
||||
}
|
||||
|
||||
public class TaskStatistics
|
||||
{
|
||||
public int TotalTasks { get; set; } = 0;
|
||||
public int CompletedTasks { get; set; } = 0;
|
||||
public int FailedTasks { get; set; } = 0;
|
||||
public int InProgressTasks { get; set; } = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using LMS.Common.Extensions;
|
||||
using LMS.Repository.DB;
|
||||
|
||||
namespace LMS.Repository.MJPackage
|
||||
{
|
||||
// Models/TokenCacheItem.cs
|
||||
public class TokenCacheItem
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string Token { get; set; }
|
||||
public string UseToken { get; set; } // 实际请求使用的Token
|
||||
public int DailyLimit { get; set; }
|
||||
public int TotalLimit { get; set; }
|
||||
public int ConcurrencyLimit { get; set; } // 新增:并发限制
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? ExpiresAt { get; set; }
|
||||
public int DailyUsage { get; set; }
|
||||
public int TotalUsage { get; set; }
|
||||
public DateTime LastActivityTime { get; set; } = BeijingTimeExtension.GetBeijingTime();
|
||||
public string? HistoryUse { get; set; } // 历史使用记录
|
||||
|
||||
public int CurrentlyExecuting { get; set; } = 0;
|
||||
}
|
||||
|
||||
public class TokenAndTaskCollection : TokenCacheItem
|
||||
{
|
||||
public List<MJApiTasks> TaskCollections { get; set; } = [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace LMS.Repository.MJPackage
|
||||
{
|
||||
public class TokenCacheStats
|
||||
{
|
||||
public int TotalTokens { get; set; }
|
||||
public int ActiveTokens { get; set; }
|
||||
public int InactiveTokens { get; set; }
|
||||
public int TotalDailyUsage { get; set; }
|
||||
public int TotalUsage { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace LMS.Repository.MJPackage
|
||||
{
|
||||
// 查询结果映射类
|
||||
public class TokenQueryResult
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string Token { get; set; }
|
||||
public string UseToken { get; set; } // 实际请求使用的Token
|
||||
public int DailyLimit { get; set; }
|
||||
public int TotalLimit { get; set; }
|
||||
public int ConcurrencyLimit { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? ExpiresAt { get; set; }
|
||||
public int DailyUsage { get; set; }
|
||||
public int TotalUsage { get; set; }
|
||||
public DateTime LastActivityTime { get; set; }
|
||||
|
||||
public string? HistoryUse { get; set; } // 历史使用记录
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace LMS.Repository.MJPackage
|
||||
{
|
||||
public class TokenUsageData
|
||||
{
|
||||
public long TokenId { get; set; }
|
||||
public DateTime Date { get; set; }
|
||||
public int DailyUsage { get; set; }
|
||||
public int TotalUsage { get; set; }
|
||||
public DateTime LastActivityTime { get; set; }
|
||||
public string? HistoryUse { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using static LMS.Common.Enums.MachineEnum;
|
||||
|
||||
namespace LMS.Repository.Models.Machine
|
||||
namespace LMS.Repository.Machine
|
||||
{
|
||||
public class MachineModel
|
||||
{
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
using LMS.Common.Enums;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Repository.Options;
|
||||
|
||||
public class AddOptionModel
|
||||
{
|
||||
|
||||
[Required]
|
||||
public required string Key { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Value of the option,这个值是一个json字符串
|
||||
/// </summary>
|
||||
public string? Value { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
public OptionTypeEnum Type { get; set; } = OptionTypeEnum.String;
|
||||
|
||||
[Required]
|
||||
public OptionCategory Category { get; set; } = OptionCategory.System;
|
||||
|
||||
[Required]
|
||||
public List<string> RoleNames { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
using LMS.Common.Enums;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Repository.Options;
|
||||
|
||||
public class ModifyOptionByKeyModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Value of the option,这个值是一个json字符串
|
||||
/// </summary>
|
||||
|
||||
public required string Value { get; set; } = string.Empty;
|
||||
|
||||
public required OptionTypeEnum Type { get; set; } = OptionTypeEnum.String;
|
||||
|
||||
public required OptionCategory Category { get; set; } = OptionCategory.System;
|
||||
[Required]
|
||||
public required List<string> RoleNames { get; set; } = [];
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Repository.Options;
|
||||
|
||||
public class ModofyOptionsModel
|
||||
{
|
||||
[Required]
|
||||
public required string Key { get; set; }
|
||||
|
||||
[Required]
|
||||
public string Value { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace LMS.Repository.Options
|
||||
{
|
||||
public class ResetUserFreeCountSettingModel
|
||||
{
|
||||
public bool EnableMonthlyReset { get; set; } = false;
|
||||
|
||||
public int OnceFreeCount { get; set; } = 5;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using LMS.Common.Enums;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Repository.Other
|
||||
{
|
||||
public class AddDataInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据的类型
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required DataInfoTypeEnum Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据的字符串
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required string DataString { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using LMS.Common.Enums;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using static LMS.Common.Enums.SoftwareControlEnum;
|
||||
|
||||
namespace LMS.Repository.Other
|
||||
{
|
||||
public class AddMachineAuthorization
|
||||
{
|
||||
/// <summary>
|
||||
/// 机器码或者是授权码
|
||||
/// </summary>
|
||||
public string? MachineID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 可用时间
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required SoftwareControlValidityEnum ExpiryTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 过期日期
|
||||
/// </summary>
|
||||
|
||||
public DateTime? ExpiryDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权使用状态
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required MachineAuthorizationUseTypeEnum UseType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权码
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required string AuthorizationCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权软件类型
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required MachineAuthorizationEnum Type { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using static LMS.Common.Enums.PermissionEnum;
|
||||
|
||||
namespace LMS.Repository.RequestModel.Permission
|
||||
namespace LMS.Repository.Promission
|
||||
{
|
||||
public class PermissionModel
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using static LMS.Common.Enums.PermissionEnum;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Repository.Models.Promission
|
||||
namespace LMS.Repository.Promission
|
||||
{
|
||||
public class PermissionTypeModel
|
||||
{
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Repository.PromptModel;
|
||||
|
||||
public class ModifyPromptModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词类型
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string PromptTypeId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词预设字符串
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string PromptString { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 描述
|
||||
/// </summary>
|
||||
public string? Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string? Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 版本
|
||||
/// </summary>
|
||||
public int Version { get; set; }
|
||||
|
||||
[Required]
|
||||
/// <summary>
|
||||
/// 状态
|
||||
/// </summary>
|
||||
public string Status { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Repository.PromptModel;
|
||||
|
||||
public class ModifyPromptTypeModal
|
||||
{
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 提示词类型编码
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string? Remark { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using LMS.Common.Attributes;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LMS.Repository.Software
|
||||
{
|
||||
public class AddSoftwareModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 软件名称
|
||||
/// </summary>
|
||||
[Required]
|
||||
[NotEmpty(ErrorMessage = "123")]
|
||||
public string SoftwareName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 软件代码
|
||||
/// </summary>
|
||||
[Required]
|
||||
[NotEmpty(ErrorMessage = "123")]
|
||||
public string SoftwareCode { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using LMS.Common.Enums;
|
||||
|
||||
namespace LMS.Repository.Software
|
||||
{
|
||||
public class ModifySoftwareControlValidityModel
|
||||
{
|
||||
public SoftwareControlEnum.SoftwareControlValidityEnum? ExpirationTime { get; set; }
|
||||
|
||||
public bool? IsForever { get; set; }
|
||||
|
||||
public bool? IsTry { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace LMS.Repository.User;
|
||||
public class LoginResponseBase
|
||||
{
|
||||
|
||||
public string Token { get; set; }
|
||||
public string UserName { get; set; }
|
||||
public long Id { get; set; }
|
||||
public string NickName { get; set; }
|
||||
}
|
||||
|
||||
public class LoginResponse : LoginResponseBase
|
||||
{
|
||||
public string RefreshToken { get; set; }
|
||||
}
|
||||
|
||||
public class SimpleLoginResponse : LoginResponseBase
|
||||
{
|
||||
public bool IsForver { get; set; }
|
||||
|
||||
public DateTime? ExpirationTime { get; set; }
|
||||
}
|
||||
@@ -6,7 +6,8 @@ namespace LMS.Repository.Models.User
|
||||
{
|
||||
[Required]
|
||||
public required string UserName { get; set; }
|
||||
public string? Email { get; set; }
|
||||
[Required]
|
||||
public required string Email { get; set; }
|
||||
[Required]
|
||||
public required string Password { get; set; }
|
||||
[Required]
|
||||
@@ -14,5 +15,7 @@ namespace LMS.Repository.Models.User
|
||||
|
||||
[Required]
|
||||
public required string AffiliateCode { get; set; }
|
||||
|
||||
public string? VerificationCode { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
public class ResetPasswordModel
|
||||
{
|
||||
[Required(ErrorMessage = "新密码是必填项")]
|
||||
public required string NewPassword { get; set; }
|
||||
}
|
||||
@@ -10,5 +10,7 @@
|
||||
public string? UserName { get; set; }
|
||||
public string? PhoneNumber { get; set; }
|
||||
public List<string>? RoleNames { get; set; }
|
||||
|
||||
public string? Remark { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
namespace LMS.Tools.Extensions
|
||||
{
|
||||
public class BeijingTimeExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取北京时间,将时区转换为北京时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static DateTime GetBeijingTime()
|
||||
{
|
||||
return TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow,
|
||||
TimeZoneInfo.FindSystemTimeZoneById("China Standard Time"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using LMS.DAO.OptionDAO;
|
||||
using LMS.Tools.ImageTool;
|
||||
using static LMS.Repository.DTO.FileUploadDto;
|
||||
|
||||
namespace LMS.Tools.FileTool
|
||||
{
|
||||
public static class FileService
|
||||
{
|
||||
public static byte[]? ConvertBase64ToBytes(string base64String)
|
||||
{
|
||||
if (string.IsNullOrEmpty(base64String))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// 检查是否以 "data:" 开头并包含 base64 编码,如果是则提取实际的 base64 部分
|
||||
if (base64String.StartsWith("data:"))
|
||||
{
|
||||
// 提取 base64 编码部分
|
||||
var commaIndex = base64String.IndexOf(',');
|
||||
if (commaIndex >= 0)
|
||||
{
|
||||
base64String = base64String.Substring(commaIndex + 1);
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
// 尝试将 base64 字符串转换为字节数组
|
||||
return Convert.FromBase64String(base64String);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
// 如果格式不正确,返回 null
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsValidImageFile(byte[] fileBytes)
|
||||
{
|
||||
if (fileBytes == null || fileBytes.Length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ImageTypeDetector.IsValidImage(fileBytes);
|
||||
}
|
||||
|
||||
public static async Task<UploadResult> CheckFileSize(byte[] fileBytes, double MaxFileSize)
|
||||
{
|
||||
if (fileBytes == null || fileBytes.Length == 0)
|
||||
{
|
||||
return new UploadResult
|
||||
{
|
||||
Success = false,
|
||||
Message = "文件不能为空"
|
||||
};
|
||||
}
|
||||
|
||||
if (fileBytes.Length > MaxFileSize * 1024 * 1024)
|
||||
{
|
||||
return new UploadResult
|
||||
{
|
||||
Success = false,
|
||||
Message = $"文件大小({fileBytes.Length} bytes)超过限制({MaxFileSize * 1024 * 1024} bytes)"
|
||||
};
|
||||
}
|
||||
|
||||
return new UploadResult { Success = true };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using LMS.Repository.DB;
|
||||
using LMS.Repository.FileUpload;
|
||||
using Qiniu.Http;
|
||||
using static LMS.Repository.DTO.FileUploadDto;
|
||||
|
||||
namespace LMS.Tools.FileTool
|
||||
{
|
||||
public interface IQiniuService
|
||||
{
|
||||
/// <summary>
|
||||
/// 检查文件的字节大小是否符合要求
|
||||
/// </summary>
|
||||
/// <param name="fileBytes"></param>
|
||||
/// <returns></returns>
|
||||
public Task<UploadResult> CheckFileBytesSize(byte[] fileBytes);
|
||||
|
||||
/// <summary>
|
||||
/// 生成七牛云上传的路径 key
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="fileName"></param>
|
||||
/// <returns></returns>
|
||||
string GenerateFileKey(long userId, string fileName);
|
||||
|
||||
/// <summary>
|
||||
/// 计算文件的 SHA1 哈希值
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
string ComputeSHA1Hash(byte[] data);
|
||||
|
||||
/// <summary>
|
||||
/// 获取七牛云的配置 用于上传图片
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<QiniuSettings> InitQiniuSetting();
|
||||
|
||||
/// <summary>
|
||||
/// 生成七牛的上传凭证
|
||||
/// </summary>
|
||||
/// <param name="qiniuSettings"></param>
|
||||
/// <returns></returns>
|
||||
string GeneratePolicy(QiniuSettings qiniuSettings);
|
||||
|
||||
/// <summary>
|
||||
/// 将 byte 数组上传到七牛云
|
||||
/// </summary>
|
||||
/// <param name="fileBytes"></param>
|
||||
/// <returns></returns>
|
||||
Task<FileUploads> UploadFileToQiNiu(byte[] fileBytes, long userId, string fileName, string fileKey);
|
||||
|
||||
/// <summary>
|
||||
/// 构建文件的访问 URL
|
||||
/// </summary>
|
||||
/// <param name="domain"></param>
|
||||
/// <param name="fileKey"></param>
|
||||
/// <returns></returns>
|
||||
string BuildFileUrl(string domain, string fileKey);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
using LMS.Common.Extensions;
|
||||
using LMS.DAO.OptionDAO;
|
||||
using LMS.Repository.DB;
|
||||
using LMS.Repository.FileUpload;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Qiniu.Http;
|
||||
using Qiniu.IO;
|
||||
using Qiniu.IO.Model;
|
||||
using Qiniu.Util;
|
||||
using System.Security.Cryptography;
|
||||
using static LMS.Repository.DTO.FileUploadDto;
|
||||
|
||||
namespace LMS.Tools.FileTool
|
||||
{
|
||||
public class QiniuService(OptionGlobalDAO optionGlobalDAO, ILogger<QiniuService> logger) : IQiniuService
|
||||
{
|
||||
private readonly OptionGlobalDAO _optionGlobalDAO = optionGlobalDAO;
|
||||
private readonly UploadManager _uploadManager = new UploadManager();
|
||||
private readonly ILogger<QiniuService> _logger = logger;
|
||||
|
||||
/// <summary>
|
||||
/// 检查文件的字节大小是否符合要求
|
||||
/// </summary>
|
||||
/// <param name="fileBytes"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<UploadResult> CheckFileBytesSize(byte[] fileBytes)
|
||||
{
|
||||
if (fileBytes == null || fileBytes.Length == 0)
|
||||
{
|
||||
return new UploadResult
|
||||
{
|
||||
Success = false,
|
||||
Message = "文件字节数据不能为空"
|
||||
};
|
||||
}
|
||||
|
||||
double MaxFileSize = await _optionGlobalDAO.FindAndReturnOption<double>("SYS_MaxUploadFileSize");
|
||||
|
||||
if (fileBytes.Length > MaxFileSize * 1024 * 1024)
|
||||
{
|
||||
return new UploadResult
|
||||
{
|
||||
Success = false,
|
||||
Message = $"文件大小不能超过 {MaxFileSize}MB"
|
||||
};
|
||||
}
|
||||
|
||||
return new UploadResult { Success = true, Message = string.Empty };
|
||||
}
|
||||
|
||||
public string ComputeSHA1Hash(byte[] data)
|
||||
{
|
||||
var hash = SHA1.HashData(data);
|
||||
return Convert.ToHexString(hash).ToLower();
|
||||
}
|
||||
|
||||
public string GenerateFileKey(long userId, string fileName)
|
||||
{
|
||||
var date = DateTime.Now.ToString("yyyyMMdd");
|
||||
//var extension = Path.GetExtension(fileName);
|
||||
return $"user/{userId}/{date}/{fileName}";
|
||||
}
|
||||
|
||||
public async Task<QiniuSettings> InitQiniuSetting()
|
||||
{
|
||||
QiniuSettings? qiniuSettings = await _optionGlobalDAO.FindAndReturnOption<QiniuSettings>("SYS_QiniuSetting");
|
||||
|
||||
if (qiniuSettings == null || string.IsNullOrEmpty(qiniuSettings.AccessKey) || string.IsNullOrEmpty(qiniuSettings.SecretKey) || string.IsNullOrEmpty(qiniuSettings.BucketName) || string.IsNullOrEmpty(qiniuSettings.Domain))
|
||||
{
|
||||
throw new Exception("七牛云配置不完整,请检查配置,请联系管理员");
|
||||
}
|
||||
return qiniuSettings;
|
||||
}
|
||||
|
||||
public string GeneratePolicy(QiniuSettings qiniuSettings)
|
||||
{
|
||||
Mac mac = new(qiniuSettings.AccessKey, qiniuSettings.SecretKey);
|
||||
var putPolicy = new PutPolicy
|
||||
{
|
||||
Scope = qiniuSettings.BucketName
|
||||
};
|
||||
if (qiniuSettings.DeleteDay != null)
|
||||
{
|
||||
putPolicy.DeleteAfterDays = qiniuSettings.DeleteDay.Value; // 设置过期时间
|
||||
}
|
||||
putPolicy.SetExpires(3600);
|
||||
string token = Auth.CreateUploadToken(mac, putPolicy.ToJsonString());
|
||||
return token;
|
||||
}
|
||||
|
||||
public string BuildFileUrl(string domain, string fileKey)
|
||||
{
|
||||
return $"{domain}/{fileKey}";
|
||||
}
|
||||
|
||||
public async Task<FileUploads> UploadFileToQiNiu(byte[] fileBytes, long userId, string fileName, string fileKey)
|
||||
{
|
||||
QiniuSettings qiniuSettings = await InitQiniuSetting();
|
||||
string token = GeneratePolicy(qiniuSettings);
|
||||
string hash = ComputeSHA1Hash(fileBytes);
|
||||
HttpResult uploadResult;
|
||||
|
||||
_logger.LogInformation("开始上传文件, 用户ID: {userId}, 文件名: {fileName}, 文件大小: {fileLength} 字节, 文件Key: {fileKey}", userId, fileName, fileBytes.Length, fileKey);
|
||||
|
||||
using (var stream = new MemoryStream(fileBytes))
|
||||
{
|
||||
uploadResult = await _uploadManager.UploadStreamAsync(stream, fileKey, token);
|
||||
}
|
||||
// 8. 检查上传结果
|
||||
if (uploadResult.Code != 200)
|
||||
{
|
||||
_logger.LogError("文件上传失败, 上传用户ID: {userId}, 错误信息: {error}", userId, uploadResult.Text);
|
||||
throw new Exception(uploadResult.Text);
|
||||
}
|
||||
|
||||
var qiniuUrl = BuildFileUrl(qiniuSettings.Domain, fileKey);
|
||||
|
||||
_logger.LogInformation("文件上传成功, 上传用户ID: {userId}, 文件Key: {fileKey},文件链接: {url}", userId, fileKey, qiniuUrl);
|
||||
return new FileUploads
|
||||
{
|
||||
UserId = userId,
|
||||
FileName = fileName,
|
||||
FileKey = fileKey,
|
||||
FileSize = fileBytes.Length,
|
||||
ContentType = "application/octet-stream",
|
||||
Hash = hash,
|
||||
QiniuUrl = qiniuUrl,
|
||||
UploadTime = DateTime.Now,
|
||||
Status = "active",
|
||||
CreatedAt = DateTime.Now,
|
||||
DeleteTime = qiniuSettings.DeleteDay != null ? BeijingTimeExtension.GetBeijingTime().AddDays((double)qiniuSettings.DeleteDay) : new DateTime(2099, 12, 31, 23, 59, 59) // 默认未删除
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
using LMS.Tools.FileTool;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text;
|
||||
|
||||
namespace LMS.Tools.HttpTool
|
||||
{
|
||||
/// <summary>
|
||||
/// HTTP网络请求服务
|
||||
/// </summary>
|
||||
public class HttpService : IHttpService
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly ILogger<HttpService> _logger;
|
||||
|
||||
public HttpService(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
ILogger<HttpService> logger)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载文件并返回字节数组
|
||||
/// </summary>
|
||||
/// <param name="url">文件URL</param>
|
||||
/// <returns>文件字节数组</returns>
|
||||
public async Task<byte[]?> DownloadFileAsync(string url, double maxFileSize)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(url))
|
||||
throw new ArgumentException("URL不能为空", nameof(url));
|
||||
|
||||
if (!Uri.IsWellFormedUriString(url, UriKind.Absolute))
|
||||
throw new ArgumentException("无效的URL格式", nameof(url));
|
||||
|
||||
using var httpClient = _httpClientFactory.CreateClient("HttpService");
|
||||
using var response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
throw new HttpRequestException($"HTTP请求失败,状态码: {response.StatusCode}");
|
||||
}
|
||||
|
||||
// 检查文件大小
|
||||
if (response.Content.Headers.ContentLength.HasValue)
|
||||
{
|
||||
if (response.Content.Headers.ContentLength.Value > maxFileSize * 1024 * 1024)
|
||||
{
|
||||
throw new InvalidOperationException($"文件大小({response.Content.Headers.ContentLength.Value} bytes)超过限制({maxFileSize * 1024 * 1024} bytes)");
|
||||
}
|
||||
}
|
||||
|
||||
var fileBytes = await response.Content.ReadAsByteArrayAsync();
|
||||
|
||||
if (fileBytes.Length > maxFileSize * 1024 * 1024)
|
||||
{
|
||||
throw new InvalidOperationException($"下载的文件大小({fileBytes.Length} bytes)超过限制({maxFileSize * 1024 * 1024} bytes)");
|
||||
}
|
||||
|
||||
return fileBytes;
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
_logger.LogError(ex, "HTTP请求异常: {Url}", url);
|
||||
throw;
|
||||
}
|
||||
catch (TaskCanceledException ex)
|
||||
{
|
||||
_logger.LogError(ex, "请求超时: {Url}", url);
|
||||
throw new TimeoutException("请求超时", ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "下载文件失败: {Url}", url);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送GET请求
|
||||
/// </summary>
|
||||
/// <param name="url">请求URL</param>
|
||||
/// <returns>响应内容</returns>
|
||||
public async Task<string> GetAsync(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(url))
|
||||
throw new ArgumentException("URL不能为空", nameof(url));
|
||||
|
||||
using var httpClient = _httpClientFactory.CreateClient("HttpService");
|
||||
var response = await httpClient.GetStringAsync(url);
|
||||
return response;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "GET请求失败: {Url}", url);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送POST请求
|
||||
/// </summary>
|
||||
/// <param name="url">请求URL</param>
|
||||
/// <param name="content">请求内容</param>
|
||||
/// <returns>响应内容</returns>
|
||||
public async Task<string> PostAsync(string url, string content)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(url))
|
||||
throw new ArgumentException("URL不能为空", nameof(url));
|
||||
|
||||
using var httpClient = _httpClientFactory.CreateClient("HttpService");
|
||||
var httpContent = new StringContent(content, Encoding.UTF8, "application/json");
|
||||
var response = await httpClient.PostAsync(url, httpContent);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "POST请求失败: {Url}", url);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查URL是否可访问
|
||||
/// </summary>
|
||||
/// <param name="url">要检查的URL</param>
|
||||
/// <returns>是否可访问</returns>
|
||||
public async Task<bool> IsUrlAccessibleAsync(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var httpClient = _httpClientFactory.CreateClient("HttpService");
|
||||
using var response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取URL的Content-Type
|
||||
/// </summary>
|
||||
/// <param name="url">要检查的URL</param>
|
||||
/// <returns>Content-Type</returns>
|
||||
public async Task<string?> GetContentTypeAsync(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var httpClient = _httpClientFactory.CreateClient("HttpService");
|
||||
using var response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
return response.Content.Headers.ContentType?.MediaType;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
namespace LMS.Tools.HttpTool
|
||||
{
|
||||
/// <summary>
|
||||
/// HTTP服务接口
|
||||
/// </summary>
|
||||
public interface IHttpService
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载文件并返回字节数组
|
||||
/// </summary>
|
||||
/// <param name="url">文件URL</param>
|
||||
/// <param name="maxFileSize">最大文件大小限制(字节)</param>
|
||||
/// <returns>文件字节数组</returns>
|
||||
Task<byte[]?> DownloadFileAsync(string url, double maxFileSize);
|
||||
|
||||
/// <summary>
|
||||
/// 发送GET请求
|
||||
/// </summary>
|
||||
/// <param name="url">请求URL</param>
|
||||
/// <returns>响应内容</returns>
|
||||
Task<string> GetAsync(string url);
|
||||
|
||||
/// <summary>
|
||||
/// 发送POST请求
|
||||
/// </summary>
|
||||
/// <param name="url">请求URL</param>
|
||||
/// <param name="content">请求内容</param>
|
||||
/// <returns>响应内容</returns>
|
||||
Task<string> PostAsync(string url, string content);
|
||||
|
||||
/// <summary>
|
||||
/// 检查URL是否可访问
|
||||
/// </summary>
|
||||
/// <param name="url">要检查的URL</param>
|
||||
/// <returns>是否可访问</returns>
|
||||
Task<bool> IsUrlAccessibleAsync(string url);
|
||||
|
||||
/// <summary>
|
||||
/// 获取URL的Content-Type
|
||||
/// </summary>
|
||||
/// <param name="url">要检查的URL</param>
|
||||
/// <returns>Content-Type</returns>
|
||||
Task<string?> GetContentTypeAsync(string url);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
namespace LMS.Tools.ImageTool
|
||||
{
|
||||
public static class ImageTypeDetector
|
||||
{
|
||||
private static readonly Dictionary<string, byte[]> ImageSignatures = new()
|
||||
{
|
||||
{ "image/jpeg", new byte[] { 0xFF, 0xD8, 0xFF } },
|
||||
{ "image/png", new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A } },
|
||||
{ "image/gif", new byte[] { 0x47, 0x49, 0x46, 0x38 } }, // GIF8
|
||||
{ "image/bmp", new byte[] { 0x42, 0x4D } }, // BM
|
||||
{ "image/webp", new byte[] { 0x52, 0x49, 0x46, 0x46 } } // RIFF (需要额外检查)
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否为支持的图片格式
|
||||
/// </summary>
|
||||
/// <param name="fileBytes">文件字节数组</param>
|
||||
/// <returns>是否为图片</returns>
|
||||
public static bool IsValidImage(byte[] fileBytes)
|
||||
{
|
||||
if (fileBytes == null || fileBytes.Length < 8)
|
||||
return false;
|
||||
|
||||
// 检查 JPEG
|
||||
if (StartsWithBytes(fileBytes, ImageSignatures["image/jpeg"]))
|
||||
return true;
|
||||
|
||||
// 检查 PNG
|
||||
if (StartsWithBytes(fileBytes, ImageSignatures["image/png"]))
|
||||
return true;
|
||||
|
||||
// 检查 GIF
|
||||
if (StartsWithBytes(fileBytes, ImageSignatures["image/gif"]))
|
||||
return true;
|
||||
|
||||
// 检查 BMP
|
||||
if (StartsWithBytes(fileBytes, ImageSignatures["image/bmp"]))
|
||||
return true;
|
||||
|
||||
// 检查 WEBP (RIFF + WEBP标识)
|
||||
if (StartsWithBytes(fileBytes, ImageSignatures["image/webp"]) &&
|
||||
fileBytes.Length >= 12 &&
|
||||
fileBytes[8] == 0x57 && fileBytes[9] == 0x45 &&
|
||||
fileBytes[10] == 0x42 && fileBytes[11] == 0x50) // "WEBP"
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool StartsWithBytes(byte[] fileBytes, byte[] signature)
|
||||
{
|
||||
if (fileBytes.Length < signature.Length)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < signature.Length; i++)
|
||||
{
|
||||
if (fileBytes[i] != signature[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,16 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\LMS.Common\LMS.Common.csproj" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" />
|
||||
<PackageReference Include="Qiniu.Shared" Version="7.2.15" />
|
||||
<PackageReference Include="Quartz.AspNetCore" Version="3.14.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\LMS.DAO\LMS.DAO.csproj" />
|
||||
<ProjectReference Include="..\LMS.Repository\LMS.Repository.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
using LMS.Repository.DB;
|
||||
using LMS.Repository.MJPackage;
|
||||
|
||||
|
||||
namespace LMS.Tools.MJPackage
|
||||
{
|
||||
// Services/ITaskConcurrencyManager.cs
|
||||
public interface ITaskConcurrencyManager
|
||||
{
|
||||
Task CreateTaskAsync(string token, string thirdPartyTaskId, MJSubmitImageModel model);
|
||||
|
||||
Task CreateErrorTaskAsync(string token, MJSubmitImageModel model, string description);
|
||||
Task UpdateTaskInDatabase(MJApiTasks mJApiTasks);
|
||||
|
||||
Task BatchUpdateTaskChaheToDatabaseAsync();
|
||||
|
||||
Task<MJApiTasks?> GetTaskInfoByThirdPartyIdAsync(string taskId);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user