• .net6 WebApi使用工厂模式+IOC


    sqlsugar:

    using SqlSugar;
    
    namespace MyFanucApi.Service
    {
        public interface ISqlSugarHelper
        {
            SqlSugarClient Db { get; }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    using MyFanucApi.Service.Sugar;
    using SqlSugar;
    
    namespace MyFanucApi.Service.Impl
    {
        public class SqlSugarHelper : ISqlSugarHelper
        {
            public SqlSugarHelper(ISqlSugarService sqlSugarServiceImpl)
            {
                this.sqlSugarServiceImpl = sqlSugarServiceImpl;
            }
    
            private ISqlSugarService sqlSugarServiceImpl;
            public SqlSugarClient Db
            {
                get => new SqlSugarClient(new ConnectionConfig()
                {
                    ConnectionString = this.sqlSugarServiceImpl.ConnectionStr,
                    //DbType = DbType.Sqlite,         //必填, 数据库类型
                    DbType = DbType.MySql,
                    IsAutoCloseConnection = true,       //默认false, 时候知道关闭数据库连接, 设置为true无需使用using或者Close操作
                    InitKeyType = InitKeyType.Attribute    //默认SystemTable, codefist需要使用Attribute
                });
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    namespace MyFanucApi.Service.Sugar
    {
        public interface ISqlSugarService
        {
            string ConnectionStr { get; set; }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    using MyFanucApi.Service.Sugar;
    
    namespace MyFanucApi.Service.Impl
    {
        public class SqlSugarServiceImpl : ISqlSugarService
        {
            //sqlserver
            //private string connectionStr = "server=.;uid=sa;pwd=sasa;database=SQLSUGAR4XTEST";
            //sqlite
            //private string connectionStr = "Data Source=MyDb.db";
            //mysql
            //private string connectionStr = "database='" + "mydb" + "';Data Source = '" + "127.0.0.1" + "'; User Id = '" + "root" + "'; pwd='" + "123456" + "';charset='utf8mb4';pooling=true";
            private string connectionStr = "server=127.0.0.1;Database=mydb;Uid=root;Pwd=123456;";
    
            public string ConnectionStr
            {
                get { return connectionStr; }
                set { connectionStr = value; }
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    普通实体类:

    按照泛型接口-抽象类-Impl实现

    泛型接口:

    namespace MyFanucApi.Service
    {
        public interface IEntityService<T>
        {
            int InsertEntities(List<T> entities);
    
            int InsertEntity(T entity);
    
            int UpdateEntity(T entity);
    
            int DeleteEntity(int entityId);
    
            int DeleteEntities(List<T> entities);
    
            T QueryEntity(int entityId);
    
            List<T> QueryEntity();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    抽象类 :

    using MyFanucApi.Entities.Menu;
    using SqlSugar;
    
    namespace MyFanucApi.Service.Common.Abs
    {
        public abstract class AbsMenuItemNewService : IEntityService<MenuItemNew>
        {
            private readonly SqlSugarClient db;
    
            public AbsMenuItemNewService(SqlSugarClient db)
            {
                this.db = db;
            }
            public virtual int DeleteEntities(List<MenuItemNew> entities)
            {
                return db.Deleteable<MenuItemNew>(entities).ExecuteCommand();
            }
    
            public virtual int DeleteEntity(int entityId)
            {
                return db.Deleteable<MenuItemNew>(entityId).ExecuteCommand();
            }
    
            public virtual int InsertEntities(List<MenuItemNew> entities)
            {
                return db.Insertable<MenuItemNew>(entities).ExecuteCommand();
            }
    
            public virtual int InsertEntity(MenuItemNew entity)
            {
                return db.Insertable(entity).ExecuteCommand();
            }
    
            public virtual MenuItemNew QueryEntity(int entityId)
            {
                return db.Queryable<MenuItemNew>().InSingle(entityId);
            }
    
            public virtual List<MenuItemNew> QueryEntity()
            {
                return db.Queryable<MenuItemNew>().ToList();
            }
    
            public virtual int UpdateEntity(MenuItemNew entity)
            {
                return db.Updateable<MenuItemNew>(entity).ExecuteCommand();
            }
    
            public abstract List<MenuItemNew> QueryLevelOne();
            public abstract List<MenuItemNew> QueryLevelTwo();
            public abstract List<MenuItemNew> QueryLevelThree();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    using MyFanucApi.Entities.Menu;
    using SqlSugar;
    
    namespace MyFanucApi.Service.Common.Abs
    {
        public abstract class AbsRolesItemNewService : IEntityService<RolesItemNew>
        {
            private readonly SqlSugarClient db;
    
            public AbsRolesItemNewService(SqlSugarClient db)
            {
                this.db = db;
            }
    
            public virtual int DeleteEntities(List<RolesItemNew> entities)
            {
                return db.Deleteable<RolesItemNew>(entities).ExecuteCommand();
            }
    
            public virtual int DeleteEntity(int entityId)
            {
                return db.Deleteable<RolesItemNew>(entityId).ExecuteCommand();
            }
    
            public virtual int InsertEntities(List<RolesItemNew> entities)
            {
                return db.Insertable<RolesItemNew>(entities).ExecuteCommand();
            }
    
            public virtual int InsertEntity(RolesItemNew entity)
            {
                return db.Insertable<RolesItemNew>(entity).ExecuteCommand();        }
    
            public virtual RolesItemNew QueryEntity(int entityId)
            {
                return db.Queryable<RolesItemNew>().InSingle(entityId);      }
    
            public virtual List<RolesItemNew> QueryEntity()
            {
                return db.Queryable<RolesItemNew>().ToList();
            }
    
            public virtual int UpdateEntity(RolesItemNew entity)
            {
                return db.Updateable<RolesItemNew>(entity).ExecuteCommand();
            }
    
            public abstract RolesItemNew FindRolesItemNewById(int rolesItemNewId);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    using MyFanucApi.Entities.Common;
    using SqlSugar;
    
    namespace MyFanucApi.Service.Common.Abs
    {
        public abstract class AbstractUserService : IEntityService<User>
        {
            private readonly SqlSugarClient db;
    
            public AbstractUserService(SqlSugarClient db)
            {
                this.db = db;
            }
    
            public virtual int DeleteEntities(List<User> entities)
            {
                return db.Deleteable<User>(entities).ExecuteCommand();
            }
    
            public virtual int DeleteEntity(int entityId)
            {
                return db.Deleteable<User>(entityId).ExecuteCommand();
            }
    
            public virtual int InsertEntities(List<User> entities)
            {
                return db.Insertable<User>(entities).ExecuteCommand();
            }
    
            public virtual int InsertEntity(User entity)
            {
                return db.Insertable(entity).ExecuteCommand();
            }
    
            public virtual User QueryEntity(int entityId)
            {
                return db.Queryable<User>().InSingle(entityId);
            }
    
            public virtual List<User> QueryEntity()
            {
                return db.Queryable<User>().ToList();
            }
    
    
            public virtual int UpdateEntity(User entity)
            {
                //var user = db.Queryable().Where(x => x.UserId == entity.UserId).First();
                return db.Updateable<User>(entity).ExecuteCommand();
            }
    
            public abstract User FindUserByNameAndPwd(string? userName, string? password);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    Impl实现类要显式的调用父类(抽象类的)构造函数, 所以要写base(db). 因为db已经在子类中的构造函数中定义过了, 这时base 就不需要写参数类型了

    using MyFanucApi.Entities.Menu;
    using MyFanucApi.Service.Common.Abs;
    using SqlSugar;
    
    namespace MyFanucApi.Service.Common.Impl
    {
        public class MenuItemNewServiceImpl : AbsMenuItemNewService
        {
            private readonly SqlSugarClient db;
    
            public MenuItemNewServiceImpl(SqlSugarClient db):base(db)
            {
                this.db = db;
            }
            public override List<MenuItemNew> QueryLevelOne()
            {
                return db.Queryable<MenuItemNew>().Where(x => x.level == 1).ToList();
            }
    
            public override List<MenuItemNew> QueryLevelThree()
            {
                return db.Queryable<MenuItemNew>().Where(x => x.level == 3).ToList();
            }
    
            public override List<MenuItemNew> QueryLevelTwo()
            {
                return db.Queryable<MenuItemNew>().Where(x => x.level == 2).ToList();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    using MyFanucApi.Entities.Menu;
    using MyFanucApi.Service.Common.Abs;
    using SqlSugar;
    
    namespace MyFanucApi.Service.Common.Impl
    {
        public class RolesItemNewServiceImpl : AbsRolesItemNewService
        {
            private readonly SqlSugarClient db;
    
            public RolesItemNewServiceImpl(SqlSugarClient db):base(db)
            {
                this.db = db;
            }
    
            public override RolesItemNew FindRolesItemNewById(int rolesItemNewId)
            {
                return db.Queryable<RolesItemNew>().Where(x => x.id == rolesItemNewId).First();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    using MyFanucApi.Entities.Common;
    using MyFanucApi.Service.Common.Abs;
    using SqlSugar;
    
    namespace MyFanucApi.Service.Common.Impl
    {
        public class UserServiceImpl : AbstractUserService
        {
            private readonly SqlSugarClient db;
    
            public UserServiceImpl(SqlSugarClient db) : base(db)
            {
                this.db = db;
            }
    
            public override User FindUserByNameAndPwd(string? userName, string? password)
            {
                if (userName == null || password == null)
                {
                    return new();
                }
                return db.Queryable<User>()
                    .Where(x => x.UserName == userName
                    && x.Password == password).First();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    工厂中生成:

    using MyFanucApi.Service.Common.Abs;
    
    namespace MyFanucApi.Service.Factory
    {
        public interface ICommonFactoryService
        {
            AbstractUserService UserService { get; }
    
            AbsRolesItemNewService ItemNewService { get; }
    
            AbsMenuItemNewService MenuItemNewService { get; }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    using MyFanucApi.Service.Common.Abs;
    using MyFanucApi.Service.Common.Impl;
    using MyFanucApi.Service.Impl;
    
    namespace MyFanucApi.Service.Factory.Impl
    {
        /// 
        /// 工厂实现类
        /// 
        public class CommonFactoryServiceImpl : ICommonFactoryService
        {
            private readonly SqlSugarHelper helper;
    
            public CommonFactoryServiceImpl(SqlSugarHelper helper)
            {
                this.helper = helper;
            }
            public AbstractUserService UserService => new UserServiceImpl(helper.Db);
    
            public AbsRolesItemNewService ItemNewService => new RolesItemNewServiceImpl(helper.Db);
    
            public AbsMenuItemNewService MenuItemNewService => new MenuItemNewServiceImpl(helper.Db);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    IOC中注册:

    using MyFanucApi.Entities;
    using MyFanucApi.Entities.Arr;
    using MyFanucApi.Service.Factory;
    using MyFanucApi.Service.Factory.Impl;
    using MyFanucApi.Service.Impl;
    using MyFanucApi.Service.Sugar;
    using MyFanucApi.Utils;
    using Serilog;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    
    builder.Services.AddControllers();
    builder.Services.AddCors(c => c.AddPolicy("any", p => p.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()));
    // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();
    
    builder.Services.AddDistributedMemoryCache();//启用内存缓存
    
    //client服务
    builder.Services.AddHttpClient();
    
    //AutoMapper
    builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
    
    
    
    
    //ORM
    builder.Services.AddSingleton<ISqlSugarService, SqlSugarServiceImpl>();
    builder.Services.AddSingleton<SqlSugarHelper>();
    builder.Services.AddSingleton<ICommonFactoryService, CommonFactoryServiceImpl>();
    
    //添加appsettings.json
    builder.Configuration.AddJsonFile("appsettings.json", false, true);
    var cfg = builder.Configuration;
    builder.Services.AddSingleton<IConfiguration>(cfg);
    
    //日志
    builder.Host.UseSerilog((context, logger) =>
    {
        logger.ReadFrom.Configuration(context.Configuration);
        logger.Enrich.FromLogContext();
    });
    
    
    //注册初始化任务
    builder.Services.AddSingleton<IHostedService, StartupInitializationService>();
    
    //机器人数据
    builder.Services.AddSingleton<MyXyzPwrArr>();
    builder.Services.AddSingleton<MyAlarm>();
    builder.Services.AddSingleton<MyDIArr>();
    builder.Services.AddSingleton<MyDOArr>();
    builder.Services.AddSingleton<MyRArr>();
    builder.Services.AddSingleton<MyCurrentPosArr>();
    builder.Services.AddSingleton<MyUIArr>();
    builder.Services.AddSingleton<MyGIArr>();
    builder.Services.AddSingleton<MyFanucAxisData>();
    //邮件
    builder.Services.AddSingleton(builder.Configuration.GetSection("EmailInfo").Get<EmailInfoConst>());
    
    //目录相关
    builder.Services.AddSingleton<MySession>();
    
    //Dto
    builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
    
    //session
    builder.Services.AddSession(options =>
    {
        options.IdleTimeout = TimeSpan.FromMinutes(200);
        options.Cookie.Name = "MySessionCookie"; // 设置会话Cookie的名称
        options.Cookie.MaxAge = TimeSpan.FromDays(1); // 设置会话Cookie的过期时间为1天
        options.Cookie.HttpOnly = false; // 限制客户端脚本访问Cookie
        //options.Cookie.IsEssential = true;
    });
    
    //builder.WebHost.UseUrls("http://0.0.0.0:8889");
    var app = builder.Build();
    
    // Configure the HTTP request pipeline.
    if (app.Environment.IsDevelopment())
    {
    
    }
    app.UseSwagger();
    app.UseSwaggerUI();
    app.UseCors("any");
    
    app.UseAuthorization();
    
    app.MapControllers();
    
    app.UseSession();
    
    //静态文件配置
    //app.UseStaticFiles();
    app.UseStaticFiles(new StaticFileOptions
    {
        FileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider(@"D:\TempPic"),
        RequestPath = "/TempPic" // 请求路径,可以根据需要自定义
    });
    
    app.UseDirectoryBrowser(); // 添加浏览器目录浏览功能,可选
    
    app.Run();
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110

    Controller中调用

    using Microsoft.AspNetCore.Cors;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using MyFanucApi.Entities.Menu;
    using MyFanucApi.Service.Factory;
    using MyFanucApi.Service.Impl;
    using MyFanucApi.Utils;
    
    namespace MyFanucApi.Controllers
    {
        [Route("api/private/v1/[controller]/[action]")]
        [ApiController]
        [EnableCors("any")]
        public class MenusController : ControllerBase
        {
            private readonly MySession mySession;
            private readonly ICommonFactoryService factoryService;
    
            public MenusController(MySession mySession, ICommonFactoryService factoryService)
            {
                this.mySession = mySession;
                this.factoryService = factoryService;
            }
    
            [HttpGet]
            public IActionResult Menus()
            {
                string userRole = mySession.user?.RoleName ?? "";
    
                if (mySession.UsersRole.TryGetValue(userRole, out int rolesItemNewId))
                {
                    //根据用户等级找到角色
                    mySession.RolesItemNew = factoryService.ItemNewService.FindRolesItemNewById(
                        rolesItemNewId
                    );
    
                    //一级目录   mySession.RolesItemNew.children
                    var menuItemlist = factoryService.MenuItemNewService.QueryLevelOne();
    
                    mySession.RolesItemNew.children = menuItemlist
                        .Where(
                            x =>
                                x.parentMenuItemId
                                    .Split(',')
                                    .Contains(mySession.RolesItemNew.id.ToString())
                        )
                        .ToList();
    
                    //SetMenuItemNewChildren(mySession.RolesItemNew.children);
    
                    foreach (var menuItem in mySession.RolesItemNew.children)
                    {
                        //menuItem.children
                        var m2 = factoryService.MenuItemNewService.QueryLevelTwo();
                        menuItem.children = m2.Where(
                                x =>
                                    x.parentMenuItemId.Split(',').Contains(menuItem.id.ToString())
                                    && x.parentMenuItemId
                                        .Split(',')
                                        .Contains(mySession.RolesItemNew.id.ToString())
                            )
                            .ToList();
                    }
    
                    foreach (var menuItem in mySession.RolesItemNew.children)
                    {
                        foreach (var menuItem2 in menuItem.children)
                        {
                            //menuItem2.children
                            var m3 = factoryService.MenuItemNewService.QueryLevelThree();
    
                            menuItem2.children = m3.Where(
                                    x =>
                                        x.parentMenuItemId.Split(',').Contains(menuItem2.id.ToString())
                                        && x.parentMenuItemId
                                            .Split(',')
                                            .Contains(menuItem.id.ToString())
                                        && x.parentMenuItemId
                                            .Split(',')
                                            .Contains(mySession.RolesItemNew.id.ToString())
                                )
                                .ToList();
                        }
                    }
                }
    
                return Ok(mySession.MenuItemsNew);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
  • 相关阅读:
    前端token知识梳理:token如何存储?token过期如何处理?如何无感刷新token?
    java基于微信小程序的鲜花销售购物商城 uniapp 小程序
    电力监控系统的组网方案与设计
    手把手QQ机器人制作教程,根据官方接口进行开发,基于Python语言制作的详细教程(更新中,已经更新 10课 / 30 课)
    [随笔] 具有产品意识的工程师
    基于drawio构建流程图编辑器
    基于改进樽海鞘群算法求解单目标优化问题
    这8款浏览器兼容性测试工具,用了以后测试效率可以“起飞”~~
    终于盼到了,Python 数据科学速查表中文版来了
    学习Java的第六天
  • 原文地址:https://blog.csdn.net/helldoger/article/details/133625204