From 3927fd21b562b9d34d11fcf8b443ba4a2619157a Mon Sep 17 00:00:00 2001 From: lq1405 <2769838458@qq.com> Date: Fri, 18 Oct 2024 12:44:12 +0800 Subject: [PATCH] =?UTF-8?q?V=200.0.1=20=E6=B7=BB=E5=8A=A0=E8=BD=AF?= =?UTF-8?q?=E4=BB=B6=E7=9A=84=E5=9F=BA=E7=A1=80=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LMS.Common/Dictionary/AllOptions.cs | 11 ++ LMS.Common/Dictionary/SimpleOptions.cs | 11 ++ LMS.Common/Enum/OptionTypeEnum.cs | 8 + LMS.Common/Enum/ResponseCodeEnum.cs | 7 + LMS.DAO/ApplicationDbContext.cs | 2 + LMS.Repository/DB/Options.cs | 61 +++++++ LMS.Repository/DTO/OptionsDto.cs | 16 ++ LMS.Repository/LMS.Repository.csproj | 1 + LMS.Repository/Options/ModofyOptionsModel.cs | 12 ++ LMS.service/Configuration/AutoMapperConfig.cs | 4 + .../DatabaseConfiguration.cs | 163 ++++++++++++------ .../Configuration/ServiceConfiguration.cs | 1 + LMS.service/Controllers/OptionsController.cs | 72 ++++++++ LMS.service/Controllers/SoftWareController.cs | 3 +- LMS.service/LMS.service.csproj | 1 - LMS.service/Service/OptionsService.cs | 163 ++++++++++++++++++ SQL/v0.0.1/Options.sql | 30 ++++ 17 files changed, 506 insertions(+), 60 deletions(-) create mode 100644 LMS.Common/Dictionary/AllOptions.cs create mode 100644 LMS.Common/Dictionary/SimpleOptions.cs create mode 100644 LMS.Common/Enum/OptionTypeEnum.cs create mode 100644 LMS.Repository/DB/Options.cs create mode 100644 LMS.Repository/DTO/OptionsDto.cs create mode 100644 LMS.Repository/Options/ModofyOptionsModel.cs create mode 100644 LMS.service/Controllers/OptionsController.cs create mode 100644 LMS.service/Service/OptionsService.cs create mode 100644 SQL/v0.0.1/Options.sql diff --git a/LMS.Common/Dictionary/AllOptions.cs b/LMS.Common/Dictionary/AllOptions.cs new file mode 100644 index 0000000..baebdc9 --- /dev/null +++ b/LMS.Common/Dictionary/AllOptions.cs @@ -0,0 +1,11 @@ +namespace LMS.Common.Dictionary; + +public class AllOptions +{ + public static readonly Dictionary> AllOptionsRequestQuery = new() + { + { "all", [] }, + { "tts", ["EdgeTTsRoles"] }, + { "software", ["LaitoolHomePage", "LaitoolNotice", "LaitoolUpdateContent","LaitoolVersion"]} + }; +} diff --git a/LMS.Common/Dictionary/SimpleOptions.cs b/LMS.Common/Dictionary/SimpleOptions.cs new file mode 100644 index 0000000..e2e6701 --- /dev/null +++ b/LMS.Common/Dictionary/SimpleOptions.cs @@ -0,0 +1,11 @@ +namespace LMS.Common.Dictionary; + +public class SimpleOptions +{ + public static readonly Dictionary> SimpleOptionsRequestQuery = new() + { + { "ttsrole", ["EdgeTTsRoles"] }, + { "laitoolinfo", ["LaitoolHomePage", "LaitoolNotice", "LaitoolUpdateContent", "LaitoolVersion"] }, + }; +} + diff --git a/LMS.Common/Enum/OptionTypeEnum.cs b/LMS.Common/Enum/OptionTypeEnum.cs new file mode 100644 index 0000000..d98c315 --- /dev/null +++ b/LMS.Common/Enum/OptionTypeEnum.cs @@ -0,0 +1,8 @@ +namespace LMS.Common.Enum; + +public enum OptionTypeEnum +{ + String = 1, + JSON = 2, + Number = 3, +} diff --git a/LMS.Common/Enum/ResponseCodeEnum.cs b/LMS.Common/Enum/ResponseCodeEnum.cs index 3c8ac6e..3f04303 100644 --- a/LMS.Common/Enum/ResponseCodeEnum.cs +++ b/LMS.Common/Enum/ResponseCodeEnum.cs @@ -193,6 +193,13 @@ namespace LMS.Common.Enums RoleHasUser = 9004, #endregion + + #region 配置项操作失败 + + [Result(ResponseString.DataNotExist)] + [Description("没有找到指定的配置项")] + FindOptionsFail = 10001, + #endregion } } } diff --git a/LMS.DAO/ApplicationDbContext.cs b/LMS.DAO/ApplicationDbContext.cs index 565791f..723eedd 100644 --- a/LMS.DAO/ApplicationDbContext.cs +++ b/LMS.DAO/ApplicationDbContext.cs @@ -28,6 +28,8 @@ namespace LMS.DAO public DbSet RsaKeys { get; set; } + public DbSet Options { get; set; } + protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); diff --git a/LMS.Repository/DB/Options.cs b/LMS.Repository/DB/Options.cs new file mode 100644 index 0000000..cab9e8a --- /dev/null +++ b/LMS.Repository/DB/Options.cs @@ -0,0 +1,61 @@ +using LMS.Common.Enum; +using Newtonsoft.Json; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace LMS.Repository.DB; + +public class Options +{ + [Key] + public required string Key { get; set; } = string.Empty; + + /// + /// Value of the option,这个值是一个json字符串 + /// + public string? Value { get; set; } = string.Empty; + + public OptionTypeEnum Type { get; set; } = OptionTypeEnum.String; + + // 写一个字段,映射Value,判断是不是json字符串,是的话就解析成对象 + [NotMapped] + public object? ValueObject + { + get + { + if (string.IsNullOrEmpty(Value)) + { + return Value; + } + + if (Type == OptionTypeEnum.JSON) + { + return JsonConvert.DeserializeObject(Value ?? "{}"); + } + + if (Type == OptionTypeEnum.Number) + { + return Convert.ToDouble(Value); + } + + return Value; + } + set + { + if (value == null) + { + Value = string.Empty; + return; + } + + if (Type == OptionTypeEnum.JSON) + { + Value = JsonConvert.SerializeObject(value); + } + else + { + Value = value.ToString(); + } + } + } +} diff --git a/LMS.Repository/DTO/OptionsDto.cs b/LMS.Repository/DTO/OptionsDto.cs new file mode 100644 index 0000000..e3cba67 --- /dev/null +++ b/LMS.Repository/DTO/OptionsDto.cs @@ -0,0 +1,16 @@ +using LMS.Common.Enum; +using System.ComponentModel.DataAnnotations; + +namespace LMS.Repository.DTO; + +public class OptionsDto +{ + public required string Key { get; set; } = string.Empty; + + /// + /// Value of the option,这个值是一个json字符串 + /// + public string? Value { get; set; } + + public OptionTypeEnum Type { get; set; } = OptionTypeEnum.String; +} diff --git a/LMS.Repository/LMS.Repository.csproj b/LMS.Repository/LMS.Repository.csproj index 7bdbfa6..e389625 100644 --- a/LMS.Repository/LMS.Repository.csproj +++ b/LMS.Repository/LMS.Repository.csproj @@ -12,6 +12,7 @@ + diff --git a/LMS.Repository/Options/ModofyOptionsModel.cs b/LMS.Repository/Options/ModofyOptionsModel.cs new file mode 100644 index 0000000..f3b20ca --- /dev/null +++ b/LMS.Repository/Options/ModofyOptionsModel.cs @@ -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; +} diff --git a/LMS.service/Configuration/AutoMapperConfig.cs b/LMS.service/Configuration/AutoMapperConfig.cs index 414d8b6..0ce4bb7 100644 --- a/LMS.service/Configuration/AutoMapperConfig.cs +++ b/LMS.service/Configuration/AutoMapperConfig.cs @@ -1,4 +1,5 @@ using AutoMapper; +using LMS.Repository.DB; using LMS.Repository.DTO; using LMS.Repository.DTO.UserDto; using LMS.Repository.Models.DB; @@ -26,6 +27,9 @@ namespace Lai_server.Configuration CreateMap(); CreateMap(); + + CreateMap(); + } } } diff --git a/LMS.service/Configuration/InitConfiguration/DatabaseConfiguration.cs b/LMS.service/Configuration/InitConfiguration/DatabaseConfiguration.cs index 939339d..a22d12e 100644 --- a/LMS.service/Configuration/InitConfiguration/DatabaseConfiguration.cs +++ b/LMS.service/Configuration/InitConfiguration/DatabaseConfiguration.cs @@ -1,8 +1,11 @@ using LMS.DAO; +using LMS.Repository.DB; using LMS.Repository.Models.DB; using LMS.Tools.Extensions; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; +using LMS.Common.Enum; +using System.Threading; using static LMS.Common.Enums.ResponseCodeEnum; namespace LMS.service.Configuration.InitConfiguration; @@ -14,6 +17,104 @@ namespace LMS.service.Configuration.InitConfiguration; public class DatabaseConfiguration(IServiceProvider serviceProvider) : IHostedService { private readonly IServiceProvider _serviceProvider = serviceProvider; + + /// + /// 检查用户和角色是否创建,如果没有则创建超级管理员和默认角色 + /// + /// 数据库上下文 + /// 用户管理器 + /// 角色管理器 + /// 取消令牌 + private static async Task CheckUserAndRoleNotCreat(ApplicationDbContext context, UserManager userManager, RoleManager roleManager, CancellationToken cancellationToken) + { + // 判断数据库中是否存在超级管理员,如果不存在则创建一个 + // 如果没有用户,默认没有超级管理员 + User? user = await context.Users.FirstOrDefaultAsync(x => x.UserName == "admin", cancellationToken: cancellationToken); + if (user != null) + { + return; + } + User admin = new() + { + UserName = "admin", + NickName = "admin", + Email = "admin@admin.com", + AllDeviceCount = 1, + AgentPercent = 0.50, + FreeCount = 10, + CreatedDate = BeijingTimeExtension.GetBeijingTime(), + UpdatedDate = BeijingTimeExtension.GetBeijingTime(), + }; + var result = await userManager.CreateAsync(admin, "Admin123."); + if (!result.Succeeded) + { + foreach (var s in result.Errors) + { + Console.WriteLine(s.Description); + return; + } + } + + List roleNames = + [ + "Super Admin", + "Admin", + "Agent User", + "VIP User", + "Simple User" + ]; + + for (int i = 0; i < roleNames.Count; i++) + { + // 开始添加一些默认数据。添加角色 + if (await roleManager.FindByNameAsync(roleNames[i]) == null) + { + var indentiyResult = await roleManager.CreateAsync(new Role + { + Name = roleNames[i], + CreatedUserId = admin.Id, + UpdatedUserId = admin.Id, + CreatedTime = BeijingTimeExtension.GetBeijingTime(), + UpdatedTime = BeijingTimeExtension.GetBeijingTime(), + Remark = string.Empty, + }); + Console.WriteLine(indentiyResult.Succeeded); + } + } + // 判断admin是否为超级管理员,如果不是,则添加 + if (!await userManager.IsInRoleAsync(admin, "Super Admin")) + { + await userManager.AddToRoleAsync(admin, "Super Admin"); + } + } + + /// + /// 检查所有的配置项,没有的话,创建 + /// + /// + /// + /// + private static async Task CheckOptionsNotCreat(ApplicationDbContext dbContext, CancellationToken cancellationToken) + { + List optionsKeyValue = [ + new Options { Key = "EdgeTTsRoles", Value = "[]", Type = OptionTypeEnum.JSON }, + new Options { Key = "LaitoolHomePage", Value = string.Empty, Type = OptionTypeEnum.String }, + new Options { Key = "LaitoolUpdateContent", Value = string.Empty, Type = OptionTypeEnum.String }, + new Options { Key = "LaitoolNotice", Value = string.Empty, Type = OptionTypeEnum.String }, + new Options { Key = "LaitoolVersion", Value = string.Empty, Type = OptionTypeEnum.String }, + ]; + + // 遍历所有的配置项,如果没有则添加 + foreach (var item in optionsKeyValue) + { + Options? options = await dbContext.Options.FirstOrDefaultAsync(x => x.Key == item.Key, cancellationToken: cancellationToken); + if (options == null) + { + await dbContext.Options.AddAsync(item, cancellationToken); + } + } + } + public async Task StartAsync(CancellationToken cancellationToken) { using var scope = _serviceProvider.CreateScope(); @@ -23,65 +124,13 @@ public class DatabaseConfiguration(IServiceProvider serviceProvider) : IHostedSe using var transaction = await dbContext.Database.BeginTransactionAsync(cancellationToken); try { - // 判断数据库中是不是超级管理员,没有创建一个 - // 要是没有用户,默认没有 - User? user = await dbContext.Users.FirstOrDefaultAsync(x => x.UserName == "admin", cancellationToken: cancellationToken); - if (user != null) - { - return; - } - User admin = new() - { - UserName = "admin", - NickName = "admin", - Email = "admin@admin.com", - AllDeviceCount = 1, - AgentPercent = 0.50, - FreeCount = 10, - CreatedDate = BeijingTimeExtension.GetBeijingTime(), - UpdatedDate = BeijingTimeExtension.GetBeijingTime(), - }; - var result = await userManager.CreateAsync(admin, "Admin123."); - if (!result.Succeeded) - { - foreach (var s in result.Errors) - { - Console.WriteLine(s.Description); - return; - } - } + // 检查用户和角色是否创建 + await CheckUserAndRoleNotCreat(dbContext, userManager, roleManager, cancellationToken); - List roleNames = - [ - "Super Admin", - "Admin", - "Agent User", - "VIP User", - "Simple User" - ]; + // 检查 是不是有配置项,没有的化添加 + await CheckOptionsNotCreat(dbContext, cancellationToken); - for (int i = 0; i < roleNames.Count; i++) - { - // 开始添加一些默认数据。添加角色 - if (await roleManager.FindByNameAsync(roleNames[i]) == null) - { - var indentiyResult = await roleManager.CreateAsync(new Role - { - Name = roleNames[i], - CreatedUserId = admin.Id, - UpdatedUserId = admin.Id, - CreatedTime = BeijingTimeExtension.GetBeijingTime(), - UpdatedTime = BeijingTimeExtension.GetBeijingTime(), - Remark = string.Empty, - }); - Console.WriteLine(indentiyResult.Succeeded); - } - } - // 判断判断admin是不是超级管理员,不是的话,添加 - if (!await userManager.IsInRoleAsync(admin, "Super Admin")) - { - await userManager.AddToRoleAsync(admin, "Super Admin"); - } + await dbContext.SaveChangesAsync(cancellationToken); await transaction.CommitAsync(cancellationToken); } catch (Exception ex) diff --git a/LMS.service/Configuration/ServiceConfiguration.cs b/LMS.service/Configuration/ServiceConfiguration.cs index 2b33663..4393cb3 100644 --- a/LMS.service/Configuration/ServiceConfiguration.cs +++ b/LMS.service/Configuration/ServiceConfiguration.cs @@ -26,6 +26,7 @@ namespace Lai_server.Configuration services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); // 注入 DAO diff --git a/LMS.service/Controllers/OptionsController.cs b/LMS.service/Controllers/OptionsController.cs new file mode 100644 index 0000000..7027675 --- /dev/null +++ b/LMS.service/Controllers/OptionsController.cs @@ -0,0 +1,72 @@ +using LMS.Repository.DB; +using LMS.Repository.DTO; +using LMS.Repository.Options; +using LMS.service.Service; +using LMS.Tools.Extensions; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using static LMS.Common.Enums.ResponseCodeEnum; + +namespace LMS.service.Controllers +{ + /// + /// Laitool 的配置项控制器 + /// + /// + [Route("lms/[controller]/[action]")] + [ApiController] + public class LaitoolOptionsController(OptionsService optionsService) : ControllerBase + { + private readonly OptionsService _optionsService = optionsService; + + #region 获取简单的配置项,无需权限 + /// + /// 获取简单的配置项,无需权限 + /// + /// + /// + [HttpGet("{optionsKey}")] + public async Task>>> GetSimpleOptions(string optionsKey) + { + return await _optionsService.GetSimpleOptions(optionsKey); + } + + #endregion + + #region 获取指定的操作,需要管理员权限 + + [HttpGet("{optionsKey}")] + [Authorize] + public async Task>>> GetAllOptions(string optionsKey) + { + long userId = ConvertExtension.ObjectToLong(HttpContext.Items["UserId"] ?? 0); + return await _optionsService.GetAllOptions(optionsKey, userId); + } + + #endregion + + #region 修改配置项 + + [HttpPost] + [Authorize] + public async Task>> ModifyOptions([FromBody] List model) + { + if (!ModelState.IsValid) + { + return APIResponseModel.CreateErrorResponseModel(ResponseCode.ParameterError); + } + long userId = ConvertExtension.ObjectToLong(HttpContext.Items["UserId"] ?? 0); + return await _optionsService.ModifyOptions(model, userId); + } + + #endregion + + //[HttpPost] + //[Authorize] + //public async Task>> GetOptions([FromBody] OptionsRequestModel request) + //{ + // return await _optionsService.GetOptions(request); + //} + + } +} diff --git a/LMS.service/Controllers/SoftWareController.cs b/LMS.service/Controllers/SoftWareController.cs index 18c30c0..33830ca 100644 --- a/LMS.service/Controllers/SoftWareController.cs +++ b/LMS.service/Controllers/SoftWareController.cs @@ -1,10 +1,9 @@ using Microsoft.AspNetCore.Mvc; -using System.Reflection; namespace LMS.service.Controllers { [Route("lms/[controller]/[action]")] - public class SoftWareController : Controller + public class SoftWareController : ControllerBase { //public Index() //{ diff --git a/LMS.service/LMS.service.csproj b/LMS.service/LMS.service.csproj index 5bed246..9b443d9 100644 --- a/LMS.service/LMS.service.csproj +++ b/LMS.service/LMS.service.csproj @@ -12,7 +12,6 @@ - diff --git a/LMS.service/Service/OptionsService.cs b/LMS.service/Service/OptionsService.cs new file mode 100644 index 0000000..f234527 --- /dev/null +++ b/LMS.service/Service/OptionsService.cs @@ -0,0 +1,163 @@ +using AutoMapper; +using LMS.Common.Dictionary; +using LMS.DAO; +using LMS.Repository.DB; +using LMS.Repository.DTO; +using LMS.Repository.DTO.UserDto; +using LMS.Repository.Models.DB; +using LMS.Repository.Options; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using static LMS.Common.Enums.ResponseCodeEnum; + +namespace LMS.service.Service +{ + public class OptionsService(ApplicationDbContext context, UserManager userManager, IMapper mapper) + { + private readonly ApplicationDbContext _context = context; + private readonly UserManager _userManager = userManager; + private readonly IMapper _mapper = mapper; + + #region 获取简单的配置项,无需权限 + + /// + /// 获取简单的配置项,无需权限 + /// + /// 配置项键 + /// API响应模型 + internal async Task>>> GetSimpleOptions(string optionsKey) + { + try + { + if (!SimpleOptions.SimpleOptionsRequestQuery.TryGetValue(optionsKey, out List? value)) + { + return APIResponseModel>.CreateErrorResponseModel(ResponseCode.ParameterError); + } + + // 从数据库中获取配置项 + List options = await _context.Options.Where(x => value.Contains(x.Key)).ToListAsync(); + if (options == null || options.Count <= 0) + { + return APIResponseModel>.CreateErrorResponseModel(ResponseCode.FindOptionsFail); + } + else + { + List optionsDto = options.Select(x => _mapper.Map(x)).ToList(); + + return APIResponseModel>.CreateSuccessResponseModel(optionsDto); + } + } + catch (Exception ex) + { + return APIResponseModel>.CreateErrorResponseModel(ResponseCode.SystemError, ex.Message); + } + } + #endregion + + #region 获取所有的配置项,需要管理员权限 + + /// + /// 获取所有的配置项,需要管理员权限 + /// + /// 请求用户ID + /// API响应模型 + internal async Task>>> GetAllOptions(string optionsKey, long requestUserId) + { + try + { + User? user = await _userManager.FindByIdAsync(requestUserId.ToString()); + if (user == null) + { + return APIResponseModel>.CreateErrorResponseModel(ResponseCode.FindUserByIdFail); + } + + bool isAdminOrSuperAdmin = await _userManager.IsInRoleAsync(user, "Admin") || await _userManager.IsInRoleAsync(user, "Super Admin"); + // 判断用户是不是管理员 + if (!isAdminOrSuperAdmin) + { + return APIResponseModel>.CreateErrorResponseModel(ResponseCode.NotPermissionAction); + } + + + IQueryable query = _context.Options; + if (optionsKey != "all") + { + List optionsKeyName = []; + if (AllOptions.AllOptionsRequestQuery.TryGetValue(optionsKey, out List? value)) + { + optionsKeyName = value; + } + else + { + return APIResponseModel>.CreateErrorResponseModel(ResponseCode.ParameterError); + } + query = query.Where(x => optionsKeyName.Contains(x.Key)); + } + + List options = await query.ToListAsync(); + List optionsDto = options.Select(x => new OptionsDto + { + Key = x.Key, + Value = x.Value, + Type = x.Type, + }).ToList(); + return APIResponseModel>.CreateSuccessResponseModel(optionsDto); + } + catch (Exception ex) + { + return APIResponseModel>.CreateErrorResponseModel(ResponseCode.SystemError, ex.Message); + } + } + + #endregion + + #region 修改配置项 + + /// + /// 修改配置项 + /// + /// 要修改的配置项模型列表 + /// 用户ID + /// API响应模型 + internal async Task>> ModifyOptions(List models, long userId) + { + using var transaction = await _context.Database.BeginTransactionAsync(); + try + { + User? user = await _userManager.FindByIdAsync(userId.ToString()); + if (user == null) + { + return APIResponseModel.CreateErrorResponseModel(ResponseCode.FindUserByIdFail); + } + bool isAdminOrSuperAdmin = await _userManager.IsInRoleAsync(user, "Admin") || await _userManager.IsInRoleAsync(user, "Super Admin"); + // 判断用户是不是管理员 + if (!isAdminOrSuperAdmin) + { + return APIResponseModel.CreateErrorResponseModel(ResponseCode.NotPermissionAction); + } + // 开始修改配置项 + for (int i = 0; i < models.Count; i++) + { + ModofyOptionsModel model = models[i]; + Options? options = await _context.Options.FirstOrDefaultAsync(x => x.Key == model.Key); + if (options == null) + { + return APIResponseModel.CreateErrorResponseModel(ResponseCode.FindOptionsFail); + } + options.Value = model.Value; + _context.Options.Update(options); + } + await _context.SaveChangesAsync(); + await transaction.CommitAsync(); + return APIResponseModel.CreateSuccessResponseModel("修改成功"); + } + catch (Exception ex) + { + await transaction.RollbackAsync(); + return APIResponseModel.CreateErrorResponseModel(ResponseCode.SystemError, ex.Message); + } + } + #endregion + } +} diff --git a/SQL/v0.0.1/Options.sql b/SQL/v0.0.1/Options.sql new file mode 100644 index 0000000..f8048bd --- /dev/null +++ b/SQL/v0.0.1/Options.sql @@ -0,0 +1,30 @@ +/* + Navicat Premium Dump SQL + + Source Server : 亿速云(国内) + Source Server Type : MySQL + Source Server Version : 80018 (8.0.18) + Source Host : yisurds-66dc0b453c05d4.rds.ysydb1.com:14080 + Source Schema : LMS_TEST + + Target Server Type : MySQL + Target Server Version : 80018 (8.0.18) + File Encoding : 65001 + + Date: 17/10/2024 21:42:59 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for Options +-- ---------------------------- +CREATE TABLE IF NOT EXISTS `Options` ( + `Key` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, + `Value` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL, + `Type` int(11) NOT NULL, + PRIMARY KEY (`Key`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; + +SET FOREIGN_KEY_CHECKS = 1;