TJC.Cyclops.Web.Core 2024.8.5.3

There is a newer version of this package available.
See the version list below for details.
dotnet add package TJC.Cyclops.Web.Core --version 2024.8.5.3                
NuGet\Install-Package TJC.Cyclops.Web.Core -Version 2024.8.5.3                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TJC.Cyclops.Web.Core" Version="2024.8.5.3" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add TJC.Cyclops.Web.Core --version 2024.8.5.3                
#r "nuget: TJC.Cyclops.Web.Core, 2024.8.5.3"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install TJC.Cyclops.Web.Core as a Cake Addin
#addin nuget:?package=TJC.Cyclops.Web.Core&version=2024.8.5.3

// Install TJC.Cyclops.Web.Core as a Cake Tool
#tool nuget:?package=TJC.Cyclops.Web.Core&version=2024.8.5.3                

Cyclops.FrameWork

Cyclops.FrameWork 基于aspnetcore封装的api框架,集成了一线开发的常用设置和基础功能;可以用较少的时间代价,让开发人员将精力更多地集中在业务上。

  • [√] 全局api调用和框架级异常日志,支持Knife4j接口文档的查看、调试和代码生成
  • [√] 接口入参校验,Cyclops.FrameWork中的接口参数校验完全基于System.ComponentModel.DataAnnotations,且在此基础上提供了验证数据是否存在ExistAttribute等扩展功能
  • [√] 统一返回值,无论是使用Cyclops.FrameWork中的Result及其子类,或者CSharp中的裸类型都自动返回全局统一值,从框架上避免对接混乱
  • [√] 标准化快捷文件上传、下载和excel的导入、导出,支持MS Azure和阿里OSS
  • [√] 在安全方面集成jwt认证和SafeComparisonFilter防重放攻击,并且支持多租户权限
  • [√] 标准化配置,支持Nacos

NuGet version (SAEA) License

一、配置示例

{
  "ServiceName": "Cyclops.WebApplication1",
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "AppConfig": {
    "Urls": [ "https://127.0.0.1:7000" ],
    "DisableSwagger": false,
    "HideConsoleLog": false,
    //jwt TokenManagement
    "JWTAuthConfig": {
      "Secret": "base64:HU8MlQQDHfGaQ+k+0q3z4HKJvNQUTjK5uRGodDATyKc=",
      "Issuer": "yswenli.cnblogs.com",
      "Audience": "Cyclops.FrameWork.WebApi",
      "AccessExpiration": 30
    },
    "MaxRequestSize": 5242880, //5242880,
    "UserStaticPath": true,
    "StaticPaths": [ "upload" ],
    "DisableSafeComparisonFilter": false,
    "SafeComparisonExpired": 5,
    "GloabVerifyCode": "9365"
  },
  "Domain": "https://dev-cyclops.xxx.com/service",
  "SnowId": {
    "WorkerId": 1, // 机器码 全局唯一
    "WorkerIdBitLength": 1, // 机器码位长 默认值6,取值范围 [1, 19]
    "SeqBitLength": 6 // 序列数位长 默认值6,取值范围 [3, 21](建议不小于4,值越大性能越高、Id位数也更长)
  },
  //详细数据库配置见SqlSugar官网(第一个为默认库)
  "DbConnectionOptions": {
    "EnableConsoleSql": false, // 启用控制台打印SQL
    "ConnectionConfigs": [
      {
        "ConfigId": "1300000000001", // 默认库标识-禁止修改
        "DbType": "MySql", // MySql、SqlServer、Sqlite、Oracle、PostgreSQL、Dm、Kdbndp、Oscar、MySqlConnector、Access、OpenGauss、QuestDB、HG、ClickHouse、GBase、Odbc、Custom
        "ConnectionString": "server=xxx.mysql.rds.aliyuncs.com;user id=xxx; password=xxx; Port=3306;database=xxx; pooling=true",
        //"DbType": "MySql",
        //"ConnectionString": "",
        "DbSettings": {
          "EnableInitDb": false, // 启用库初始化
          "EnableDiffLog": false, // 启用库表差异日志
          "EnableUnderLine": true // 启用驼峰转下划线
        },
        "TableSettings": {
          "EnableInitTable": false, // 启用表初始化
          "EnableIncreTable": false // 启用表增量更新-特性[IncreTable]
        },
        "SeedSettings": {
          "EnableInitSeed": false, // 启用种子初始化
          "EnableIncreSeed": true // 启用种子增量更新-特性[IncreSeed]
        }
      }
      // 日志独立数据库配置
      //,{
      //  "ConfigId": "1300000000002", // 日志库标识-禁止修改
      //  "DbType": "Sqlite",
      //  "ConnectionString": "DataSource=./TJCES.Cyclops.Log.db", // 库连接字符串
      //  "DbSettings": {
      //    "EnableInitDb": true, // 启用库初始化
      //    "EnableDiffLog": false, // 启用库表差异日志
      //    "EnableUnderLine": false // 启用驼峰转下划线
      //  },
      //  "TableSettings": {
      //    "EnableInitTable": true, // 启用表初始化
      //    "EnableIncreTable": false // 启用表增量更新-特性[IncreTable]
      //  },
      //  "SeedSettings": {
      //    "EnableInitSeed": false, // 启用种子初始化
      //    "EnableIncreSeed": false // 启用种子增量更新-特性[IncreSeed]
      //  }
      //}
      //// 其他数据库配置(可以配置多个)
      //,{
      //  "ConfigId": "test", // 库标识
      //  "DbType": "Sqlite", // 库类型
      //  "ConnectionString": "DataSource=./TJCES.Cyclops.Test.db", // 库连接字符串
      //  "DbSettings": {
      //    "EnableInitDb": true, // 启用库初始化
      //    "EnableDiffLog": false, // 启用库表差异日志
      //    "EnableUnderLine": false // 启用驼峰转下划线
      //  },
      //  "TableSettings": {
      //    "EnableInitTable": true, // 启用表初始化
      //    "EnableIncreTable": false // 启用表增量更新-特性[IncreTable]
      //  },
      //  "SeedSettings": {
      //    "EnableInitSeed": true, // 启用种子初始化
      //    "EnableIncreSeed": false // 启用种子增量更新-特性[IncreSeed]
      //  }
      //}
    ]
  },
  //图形验证码
  "CaptchaOptions": {
    "CaptchaType": 2, // 验证码类型0、1、2、3、4、5、6、7、8、9、10、11
    "CodeLength": 4, // 验证码长度, 要放在CaptchaType设置后  当类型为算术表达式时,长度代表操作的个数, 例如2
    "ExpirySeconds": 60, // 验证码过期秒数
    "IgnoreCase": true, // 比较时是否忽略大小写
    "StoreageKeyPrefix": "", // 存储键前缀
    "ImageOption": {
      "Animation": false, // 是否启用动画
      "FontSize": 36, // 字体大小
      "Width": 150, // 验证码宽度
      "Height": 50, // 验证码高度
      "BubbleMinRadius": 5, // 气泡最小半径
      "BubbleMaxRadius": 10, // 气泡最大半径
      "BubbleCount": 3, // 气泡数量
      "BubbleThickness": 1.0, // 气泡边沿厚度
      "InterferenceLineCount": 3, // 干扰线数量
      "FontFamily": "kaiti", // 包含actionj,epilog,fresnel,headache,lexo,prefix,progbot,ransom,robot,scandal,kaiti
      "FrameDelay": 300, // 每帧延迟,Animation=true时有效, 默认300
      "BackgroundColor": "#ffffff", //  格式: rgb, rgba, rrggbb, or rrggbbaa format to match web syntax, 默认#fff
      "ForegroundColors": "", //  颜色格式同BackgroundColor,多个颜色逗号分割,随机选取。不填,空值,则使用默认颜色集
      "Quality": 100, // 图片质量(质量越高图片越大,gif调整无效可能会更大)
      "TextBold": true // 粗体
    },
    "DefaultCode": "9365"
  },
  //redis配置
  "RedisConfig": {
    "SectionName": "Redis",
    "Type": 0,
    "Password": "xxx=",
    "Masters": "xxxx:6379",
    "Slaves": null,
    "ServiceName": "mymaster",
    "DefaultDatabase": 0,
    "AllowAdmin": true,
    "KeepAlive": 180,
    "ConnectTimeout": 10000,
    "ConnectRetry": 1,
    "BusyRetry": 3,
    "BusyRetryWaitMS": 15000,
    "PoolSize": 1,
    "CommandTimeout": 60000,
    "Extention": null
  },
  //微信公众号/小程序
  "WechatOptions": {
    // 公众号-正式版公众测试号
    "WechatAppId": "xxx",
    "WechatAppSecret": "xxx",
    // 小程序
    "WxOpenAppId": "",
    "WxOpenAppSecret": ""
  },
  // 微信支付
  "WechatPayOptions": {
    "AppId": "xxx", // 微信公众平台AppId、开放平台AppId、小程序AppId、企业微信CorpId
    "MerchantId": "xxx", // 商户平台的商户号
    "MerchantV3Secret": "xxx", // 商户平台的APIv3密钥
    "MerchantCertificateSerialNumber": "xxx", // 商户平台的证书序列号
    "MerchantCertificatePrivateKey": "/WxPayCert/apiclient_key.pem", // 商户平台的API证书私钥(apiclient_key.pem文件内容)
    "WechatPayUrl": "/api/sysWechatPay/payCallBack" // 微信支付回调
  },
  //上传文件
  "UploadOptions": {
    "Path": "Upload/{yyyy}/{MM}/{dd}", // 文件上传目录
    "MaxSize": 5242880, // 文件最大限制1024*1024*50
    "ContentType": [ "image/jpg", "image/png", "image/jpeg", "image/gif", "image/bmp", "text/plain", "application/pdf", "application/msword", "application/vnd.ms-excel", "application/vnd.ms-powerpoint", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "video/mp4" ],
    "EnableMd5": true // 启用文件MDF5验证-防止重复上传
  },

  //短信
  "SmsOption": {
    "ZhuTong": {
      "UserName": "xxx",
      "Password": "xxx",
      "Signature": "【Cyclops】"
    }
  },

  //直播配置
  "LiveConfig": {
    "AppId": "xxx",
    "AppSecret": "xxx",
    "Url": "https://devapimeeting.xxx.com",
    "AuthorizeUrl": "https://devmeeting.xxx.com"
  },

  //语音转换
  "SpeechConfig": {
    "SpeechType": 1,
    "ClientId": "xxx",
    "ClientSecret": "xxx"
  }

}

AppConfig节点以下的可以与nacos集成

二、初始化代码示例

public class Program
{
    public static void Main(string[] args)
    {
        WebApp.OnStarted += WebApp_OnStarted;
        WebApp.OnStopped += WebApp_OnStopped;
        WebApp.RunWebHost<Startup>(args);
    }


    static void WebApp_OnStarted()
    {
        Logger.Info($"{WebApp.ServiceName}应用已启动");
    }


    static void WebApp_OnStopped()
    {
        Logger.Info($"{WebApp.ServiceName}应用已停止");
    }
}
    /// <summary>
    /// Startup
    /// </summary>
    public class Startup : BaseStartup
    {
        /// <summary>
        /// Startup
        /// </summary>
        /// <param name="configuration"></param>
        public Startup(IConfiguration configuration) : base(configuration)
        {

        }
    }

三、控制器示例

继承基类即可

public class AuthController : BaseApiController

方法示例

    /// <summary>
    /// Login
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [AllowAnonymous, HttpPost, DisplayName("Login")]
    public async Task<Result> Login([Required(ErrorMessage = "请输入用户名或密码"), FromBody] UserLoginInput input)
    {
        var user = new SysUser();
        return SuccessResult(await CreateToken(user));
    }

    /// <summary>
    /// 获取验证码
    /// </summary>
    /// <returns></returns>
    [AllowAnonymous]
    [SuppressMonitor]
    [DisplayName("获取验证码"), HttpGet]
    public Result GetCaptcha()
    {
        ICaptcha captcha = ServiceProviderUtil.GetRequiredService<ICaptcha>();
        var codeId = YitIdHelper.NextId().ToString();
        var captchas = captcha.Generate(codeId, 180);
        return SuccessResult(new { Id = codeId, Img = captchas.Base64 });
    }

四、集成数据校验

/// <summary>
/// 登录信息
/// </summary>
public class UserLoginInput
{
    /// <summary>
    /// 请输入用户名
    /// </summary>
    [Required(ErrorMessage = "请输入用户名"), Exists("用户名不存在", TableName = "bus_user", ColumnName = "user_name")]
    public string UserName { get; set; }
    /// <summary>
    /// 请输入密码
    /// </summary>
    [Required(ErrorMessage = "请输入密码"), Custom<UserLoginInput>("密码不正确", "Valide")]
    public string Password { get; set; }

    /// <summary>
    /// 验证密码
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public bool Valide(object? input)
    {
        if (input == null) return false;
        if (input is string password && password == "123456")
        {
            return true;
        }
        return false;

    }
}

五、防重放攻击示例

    /// <summary>
    /// 接口安全参数校验测试
    /// </summary>
    [SafeComparisonFilter]
    public class SafeController : BaseApiController
    {
        /// <summary>
        /// Test
        /// </summary>
        /// <param name="testInfo"></param>
        /// <returns></returns>
        [HttpPost]
        public Result Test([FromBody] TestInfo testInfo)
        {
            return SuccessResult(testInfo);
        }

        /// <summary>
        /// test2
        /// </summary>
        /// <returns></returns>
        [HttpGet, AllowAnonymous, NoSafeComparisonFilter]
        public Result Test2()
        {
            return SuccessResult();
        }
    }

六、文件上传下载Excel导入导出示例

   public class FileAdminController : BaseApiController
   {
       /// <summary>
       /// 导入
       /// </summary>
       /// <returns></returns>
       [HttpPost]
       [NoLoginAuth, AllowAnonymous]
       public Result Import(IFormCollection collection)
       {
           var data = collection.SaveAsDataTable();
           return SuccessResult(data);
       }


       /// <summary>
       /// 导出
       /// </summary>
       /// <returns></returns>
       [HttpPost]
       [NoLoginAuth, AllowAnonymous]
       public IActionResult Export()
       {
           return _env.Download("export.png");
       }

       /// <summary>
       /// 导出数据文件
       /// </summary>
       /// <returns></returns>
       [HttpGet]
       [NoLoginAuth, AllowAnonymous]
       public IActionResult ExportFile([FromQuery] bool isExcel = false)
       {
           var fileName = "export.xlsx";
           if (!isExcel)
           {
               fileName = "export.csv";
           }
           var dt = new DataTable();
           //return _env.ExportFile(dt, fileName);
           return Export(dt, fileName);
       }


       /// <summary>
       /// 导出数据文件
       /// </summary>
       /// <returns></returns>
       [HttpGet]
       [NoLoginAuth, AllowAnonymous]
       public IActionResult ExportDataFile([FromQuery] bool isExcel = false)
       {
           var fileName = "export.xlsx";
           if (!isExcel)
           {
               fileName = "export.csv";
           }
           var list = new List<BusUser>
           {
               new BusUser()
               {
                   Id = 1,
                   UserName = "张三"
               }
           };
           //return _env.ExportFile(list, fileName);
           return Export(list, fileName);
       }



       /// <summary>
       /// 测试上传文件大小
       /// </summary>
       /// <returns></returns>
       [HttpPost]
       public async Task<IActionResult> UploadFile(IFormCollection form)
       {
           var fileStream = await form.SaveAsStreamsAsync();

           return fileStream.First().Value.Download("test.jpg");
       }

       /// <summary>
       /// 测试限制上传文件大小
       /// </summary>
       /// <param name="form"></param>
       /// <returns></returns>

       [HttpPost, RequestSizeLimit(2 * 1024 * 1024)]
       public async Task<IActionResult> UploadFileByLimit(IFormCollection form)
       {
           var fileStream = await form.SaveAsStreamsAsync();

           return fileStream.First().Value.Download("test.jpg");
       }

       /// <summary>
       /// 测试不限制上传文件大小
       /// </summary>
       /// <param name="form"></param>
       /// <returns></returns>

       [HttpPost, DisableRequestSizeLimit]
       public async Task<IActionResult> UploadFileByNonLimit(IFormCollection form)
       {
           var fileStream = await form.SaveAsStreamsAsync();

           return fileStream.First().Value.Download("test.jpg");
       }       

      /// <summary>
      /// 示例获取流
      /// </summary>
      /// <returns></returns>
      [HttpGet]
      public async Task<Stream> GetStream()
      {
          var ms = new MemoryStream(RandomUtil.GetBytes(1024));
          return await Task.FromResult(ms);
      }

      /// <summary>
      /// 示例获取字节数组
      /// </summary>
      /// <returns></returns>
      [HttpGet]
      public async Task<byte[]> GetBytes()
      {
          return await Task.FromResult(RandomUtil.GetBytes(1024));
      }
   }

七、支持非api接口内容

        /// <summary>
        /// 返回指定内容结果
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="text"></param>
        /// <param name="contentType"></param>
        /// <param name="statusCode"></param>
        /// <returns></returns>
        public async Task<IActionResult> ContentAsync(string text, string contentType = "text/plain", int statusCode = 200)
        {
            var contentResult = new ContentResult()
            {
                Content = text,
                ContentType = contentType,
                StatusCode = statusCode
            };
            return await Task.FromResult(contentResult);
        }

        /// <summary>
        /// 返回空结果
        /// </summary>
        /// <param name="controller"></param>
        /// <returns></returns>
        public async Task<IActionResult> EmptyAsync()
        {
            return await Task.FromResult(new EmptyResult());
        }

        /// <summary>
        /// 返回下载结果
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="fileContent">下载时的文件名称</param>
        /// <param name="fileContent">内容字节数组</param>
        /// <param name="contentType">内容mime类型</param>
        /// <returns></returns>
        public async Task<IActionResult> DownloadAsync(string fileDownloadName,
            byte[] fileContent,
            string contentType)
        {
            return await Task.FromResult(new FileContentResult(fileContent, contentType) { FileDownloadName = fileDownloadName });
        }

        /// <summary>
        /// 返回下载结果
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="fileName">内容文件地址</param>
        /// <param name="contentType">内容mime类型</param>
        /// <returns></returns>
        public async Task<IActionResult> DownloadAsync(string fileName,
            string contentType)
        {
            return await Task.FromResult(new VirtualFileResult(fileName, contentType)
            {
                EnableRangeProcessing = true,
                FileDownloadName = PathUtil.GetFileName(fileName)
            });
        }
        /// <summary>
        /// 返回流结果
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="fileDownloadName"></param>
        /// <param name="fileStream"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public async Task<IActionResult> DownloadAsync(string fileDownloadName,
            Stream fileStream,
            string contentType
            )
        {
            return await Task.FromResult(new FileStreamResult(fileStream, contentType)
            {
                EnableRangeProcessing = true,
                FileDownloadName = fileDownloadName
            });
        }
        /// <summary>
        /// 返回跳转结果
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public async Task<IActionResult> RedirectAsync(string url)
        {
            return await Task.FromResult(new RedirectResult(url));
        }
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on TJC.Cyclops.Web.Core:

Package Downloads
TJC.Cyclops.Wechat

企服版框架中微信对接相关业务核心项目

TJC.Cyclops.TaskSystem

企服版任务核心

TJC.Cyclops.UCenter

企服版框架中Discuz的UCenter用户同步注册、登录

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2024.9.26.1 38 9/26/2024
2024.9.25.1 60 9/25/2024
2024.9.23.4 69 9/23/2024
2024.9.23.3 62 9/23/2024
2024.9.23.2 69 9/23/2024
2024.9.23.1 62 9/23/2024
2024.9.19.1 72 9/19/2024
2024.9.14.1 60 9/14/2024
2024.9.10.3 85 9/10/2024
2024.9.10.2 107 9/10/2024
2024.9.10.1 83 9/10/2024
2024.9.5.1 102 9/5/2024
2024.8.22.1 140 8/22/2024
2024.8.21.1 101 8/21/2024
2024.8.19.1 127 8/19/2024
2024.8.15.1 101 8/15/2024
2024.8.14.1 119 8/14/2024
2024.8.13.2 96 8/13/2024
2024.8.13.1 102 8/13/2024
2024.8.12.2 98 8/12/2024
2024.8.12.1 98 8/12/2024
2024.8.9.2 95 8/9/2024
2024.8.9.1 90 8/9/2024
2024.8.7.1 74 8/7/2024
2024.8.6.2 77 8/6/2024
2024.8.6.1 85 8/6/2024
2024.8.5.5 61 8/5/2024
2024.8.5.4 69 8/5/2024
2024.8.5.3 81 8/5/2024
2024.8.5.2 69 8/5/2024
2024.8.5.1 79 8/5/2024
2024.8.2.4 68 8/2/2024
2024.8.2.3 62 8/2/2024
2024.8.2.2 75 8/2/2024
2024.8.2.1 64 8/2/2024
2024.8.1.1 81 8/1/2024
2024.7.31.2 41 7/31/2024
2024.7.31.1 66 7/31/2024
2024.7.25.1 67 7/25/2024
2024.7.17.1 117 7/17/2024
2024.7.12.2 99 7/12/2024
2024.7.12.1 84 7/12/2024
2024.7.11.2 79 7/11/2024
2024.7.11.1 85 7/11/2024
2024.7.10.4 101 7/10/2024
2024.7.10.3 91 7/10/2024
2024.7.10.2 86 7/10/2024
2024.7.10.1 96 7/10/2024
2024.5.29.1 140 5/29/2024
2024.5.28.1 125 5/28/2024
2024.5.15.1 145 5/15/2024
2024.5.13.1 110 5/13/2024
2024.5.11.1 104 5/11/2024
2024.3.15.1 133 3/15/2024
2024.1.9.1 148 1/9/2024
2024.1.4.1 120 1/4/2024
2024.1.2.3 194 1/2/2024
2024.1.2.2 126 1/2/2024
2024.1.2.1 128 1/2/2024
2023.12.29.3 123 12/29/2023
2023.12.29.2 106 12/29/2023
2023.12.29.1 97 12/29/2023
2023.12.28.4 117 12/28/2023
2023.12.28.3 124 12/28/2023
2023.12.28.2 132 12/28/2023
2023.12.28.1 89 12/28/2023
2023.12.27.2 98 12/27/2023
2023.12.27.1 122 12/27/2023
2023.12.26.1 116 12/26/2023
2023.12.25.1 115 12/25/2023
2023.12.22.4 125 12/22/2023
2023.12.22.3 122 12/22/2023
2023.12.22.2 120 12/22/2023
2023.12.22.1 113 12/22/2023
2023.12.21.2 121 12/21/2023
2023.12.21.1 119 12/21/2023
2023.12.20.2 125 12/20/2023
2023.12.20.1 116 12/20/2023
2023.12.14.4 179 12/14/2023
2023.12.14.3 119 12/14/2023
2023.12.14.2 131 12/14/2023
2023.12.14.1 111 12/14/2023
2023.12.13.9 113 12/14/2023
2023.12.13.8 116 12/14/2023
2023.12.13.7 115 12/13/2023
2023.12.13.6 113 12/13/2023
2023.12.13.5 114 12/13/2023
2023.12.13.4 130 12/13/2023
2023.12.13.3 127 12/13/2023
2023.12.13.1 124 12/13/2023
2023.12.13 121 12/13/2023

企服版框架中api核心功能项目