在一些复杂的业务表中间查询数据,有时候操作会比较复杂一些,不过基于SqlSugar的相关操作,处理的代码会比较简单一些,以前我在随笔《基于SqlSugar的开发框架循序渐进介绍(2)-- 基于中间表的查询处理》介绍过基于主表和中间表的联合查询,而往往实际会比这个会复杂一些。本篇随笔介绍联合多个表进行查询以及树形列表的条件展示的处理实现,系统能够给大家一些参考思路。

1、SqlSugar的开发框架的数据查询处理

在随笔《基于SqlSugar的开发框架循序渐进介绍(2)-- 基于中间表的查询处理》中,介绍过两个表的联合查询,如下所示代码所示。

/// <summary>
/// 根据用户ID获取对应的角色列表
/// </summary>
/// <param name="userID">用户ID</param>
/// <returns></returns>
private async Task<List<RoleInfo>> GetByUser(int userID)
{
var query = this.Client.Queryable<RoleInfo, User_RoleInfo>(
(t, m) => t.Id == m.Role_ID && m.User_ID == userID)
.Select(t => t); //联合条件获取对象 query = query.OrderBy(t => t.CreateTime);//排序
var list = await query.ToListAsync();//获取列表
return list;
} /// <summary>
/// 根据机构获取对应的角色列表(判断机构角色中间表)
/// </summary>
/// <param name="ouID">机构的ID</param>
/// <returns></returns>
public async Task<List<RoleInfo>> GetRolesByOu(int ouID)
{
var query = this.Client.Queryable<RoleInfo, OU_RoleInfo>(
(t, m) => t.Id == m.Role_ID && m.Ou_ID == ouID)
.Select(t => t); //联合条件获取对象 query = query.OrderBy(t => t.CreateTime);//排序
var list = await query.ToListAsync();//获取列表
return list;
}

我们对于后端的数据查询,一般都是传入一个条件对象,通过条件类的属性进行构建查询信息,如下简单的处理操作。

/// <summary>
/// 应用层服务接口实现
/// </summary>
public class CustomerService : MyCrudService<CustomerInfo, string, CustomerPagedDto>, ICustomerService
{
/// <summary>
/// 自定义条件处理
/// </summary>
/// <param name="input">查询条件Dto</param>
/// <returns></returns>
protected override ISugarQueryable<CustomerInfo> CreateFilteredQueryAsync(CustomerPagedDto input)
{
var query = base.CreateFilteredQueryAsync(input); query = query
.WhereIF(!input.ExcludeId.IsNullOrWhiteSpace(), t => t.Id != input.ExcludeId) //不包含排除ID
.WhereIF(!input.Name.IsNullOrWhiteSpace(), t => t.Name.Contains(input.Name)) //如需要精确匹配则用Equals
//年龄区间查询
.WhereIF(input.AgeStart.HasValue, s => s.Age >= input.AgeStart.Value)
.WhereIF(input.AgeEnd.HasValue, s => s.Age <= input.AgeEnd.Value) //创建日期区间查询
.WhereIF(input.CreateTimeStart.HasValue, s => s.CreateTime >= input.CreateTimeStart.Value)
.WhereIF(input.CreateTimeEnd.HasValue, s => s.CreateTime <= input.CreateTimeEnd.Value)
; return query;
}

上面的 CreateFilteredQueryAsync 方法是一个基类函数,主要是构建该业务表的一些数据查询的匹配处理,如对于复杂一些的查询条件,这个内容会增加很多,不过都是可以通过代码生成工具基于数据库表字段来进行一一对应的生成,从而避免人工繁琐的敲击代码。

如下面是基类函数的常规条件查询和计数的函数处理。

/// <summary>
/// 根据条件获取列表
/// </summary>
/// <param name="input">分页查询条件</param>
/// <returns></returns>
public virtual async Task<PagedResultDto<TEntity>> GetListAsync(TGetListInput input)
{
var query = CreateFilteredQueryAsync(input);
var totalCount = await query.CountAsync(); query = ApplySorting(query, input);
query = ApplyPaging(query, input); var list = await query.ToListAsync(); return new PagedResultDto<TEntity>(
totalCount,
list
);
} /// <summary>
/// 根据条件计算记录数量
/// </summary>
/// <param name="input">查询条件,忽略分页信息</param>
/// <returns></returns>
public virtual async Task<long> CountAsync(TGetListInput input)
{
var query = CreateFilteredQueryAsync(input); var totalCount = await query.CountAsync();
return totalCount; //返回符合条件的所有数量
}

上面的 CreateFilteredQueryAsync 方法一般会在具体的业务类中进行重写,从而实现具体条件的查询过滤。

2、对于多表的联合处理操作

而对于复杂的多表之间的联合查询处理,如果分开多个函数来实现,可能会比较麻烦,而且也不够统一,因此我们可以统一整合在CreateFilteredQueryAsync 实现。

而一些特殊的条件,我们可以在原有生成的条件分页类里面,增加更多的属性,用来在联合查询中赋值、或者获取值。如下图是我们额外增加的几个特殊的属性,用来在其他业务表中进行关联查询的字段。

由于客户分组是在另外一张表里面记录的,客户和分组之间的关联,是通过中间表的联合查询获得的。

客户和供应商也有一个中间表的关联关系,因此我们如何联合查询,根据条件,可以通过下面的代码进行联合查询获得。

            if (!input.GroupId.IsNullOrWhiteSpace())
{
// 联合 CustomerGroup_CustomerInfo 表进行查询
query = this.Client.Queryable<CustomerInfo, CustomerGroup_CustomerInfo>(
(t, m) => t.Id == m.Customer_ID && m.CustomerGroup_ID == input.GroupId)
.Select(t => t).MergeTable(); //联合条件获取对象
}
if(!input.SupplierId.IsNullOrEmpty())
{
query = this.Client.Queryable<CustomerInfo, Customer_SupplierInfo>(
(t, m) => t.Id == m.Customer_ID && m.Supplier_ID == input.SupplierId)
.Select(t => t).MergeTable(); //联合条件获取对象
}

上面的代码,需要注意的是,不同表之间联合获得的结果,如果需要整合到主表进行的查询中,则需要使用 .MergeTable() 操作进行合并处理。

这种最终我们可以得到比较复杂一些的查询处理了。

        /// <summary>
/// 自定义条件处理
/// </summary>
/// <param name="input">查询条件Dto</param>
/// <returns></returns>
protected override ISugarQueryable<CustomerInfo> CreateFilteredQueryAsync(CustomerPagedDto input)
{
var query = base.CreateFilteredQueryAsync(input);
if (!input.GroupId.IsNullOrWhiteSpace())
{
// 联合 CustomerGroup_CustomerInfo 表进行查询
query = this.Client.Queryable<CustomerInfo, CustomerGroup_CustomerInfo>(
(t, m) => t.Id == m.Customer_ID && m.CustomerGroup_ID == input.GroupId)
.Select(t => t).MergeTable(); //联合条件获取对象
}
if(!input.SupplierId.IsNullOrEmpty())
{
query = this.Client.Queryable<CustomerInfo, Customer_SupplierInfo>(
(t, m) => t.Id == m.Customer_ID && m.Supplier_ID == input.SupplierId)
.Select(t => t).MergeTable(); //联合条件获取对象
} //通过名称或代码查询,任一符合即可
query = query.WhereIF(!input.NameOrCode.IsNullOrWhiteSpace(), t => t.Name.Contains(input.NameOrCode) || t.SimpleName.Contains(input.NameOrCode) || t.HandNo.Contains(input.NameOrCode)); query = query
.WhereIF(!input.ExcludeId.IsNullOrWhiteSpace(), t => t.Id != input.ExcludeId) //不包含排除ID
.WhereIF(!input.HandNo.IsNullOrWhiteSpace(), t => t.HandNo.Contains(input.HandNo)) //如需要精确匹配则用Equals
.WhereIF(!input.Name.IsNullOrWhiteSpace(), t => t.Name.Contains(input.Name)) //如需要精确匹配则用Equals
.WhereIF(!input.SimpleName.IsNullOrWhiteSpace(), t => t.SimpleName.Contains(input.SimpleName)) //如需要精确匹配则用Equals
.WhereIF(!input.Province.IsNullOrWhiteSpace(), t => t.Province.Contains(input.Province)) //如需要精确匹配则用Equals
.WhereIF(!input.City.IsNullOrWhiteSpace(), t => t.City.Contains(input.City)) //如需要精确匹配则用Equals
.WhereIF(!input.District.IsNullOrWhiteSpace(), t => t.District.Contains(input.District)) //如需要精确匹配则用Equals
.WhereIF(!input.Area.IsNullOrWhiteSpace(), t => t.Area.Contains(input.Area)) //如需要精确匹配则用Equals
.WhereIF(!input.Address.IsNullOrWhiteSpace(), t => t.Address.Contains(input.Address)) //如需要精确匹配则用Equals
.WhereIF(!input.ZipCode.IsNullOrWhiteSpace(), t => t.ZipCode.Contains(input.ZipCode)) //如需要精确匹配则用Equals
.WhereIF(!input.Telephone.IsNullOrWhiteSpace(), t => t.Telephone.Contains(input.Telephone)) //如需要精确匹配则用Equals
.WhereIF(!input.Fax.IsNullOrWhiteSpace(), t => t.Fax.Contains(input.Fax)) //如需要精确匹配则用Equals
.WhereIF(!input.Contact.IsNullOrWhiteSpace(), t => t.Contact.Contains(input.Contact)) //如需要精确匹配则用Equals
.WhereIF(!input.ContactPhone.IsNullOrWhiteSpace(), t => t.ContactPhone.Contains(input.ContactPhone)) //如需要精确匹配则用Equals
.WhereIF(!input.ContactMobile.IsNullOrWhiteSpace(), t => t.ContactMobile.Contains(input.ContactMobile)) //如需要精确匹配则用Equals
.WhereIF(!input.Email.IsNullOrWhiteSpace(), t => t.Email.Contains(input.Email)) //如需要精确匹配则用Equals
.WhereIF(!input.QQ.IsNullOrWhiteSpace(), t => t.QQ.Contains(input.QQ)) //如需要精确匹配则用Equals
.WhereIF(!input.Industry.IsNullOrWhiteSpace(), t => t.Industry.Contains(input.Industry)) //如需要精确匹配则用Equals
.WhereIF(!input.BusinessScope.IsNullOrWhiteSpace(), t => t.BusinessScope.Contains(input.BusinessScope)) //如需要精确匹配则用Equals
.WhereIF(!input.Brand.IsNullOrWhiteSpace(), t => t.Brand.Contains(input.Brand)) //如需要精确匹配则用Equals
.WhereIF(!input.PrimaryClient.IsNullOrWhiteSpace(), t => t.PrimaryClient.Contains(input.PrimaryClient)) //如需要精确匹配则用Equals
.WhereIF(!input.PrimaryBusiness.IsNullOrWhiteSpace(), t => t.PrimaryBusiness.Contains(input.PrimaryBusiness)) //如需要精确匹配则用Equals
//注册资金区间查询
.WhereIF(input.RegisterCapitalStart.HasValue, s => s.RegisterCapital >= input.RegisterCapitalStart.Value)
.WhereIF(input.RegisterCapitalEnd.HasValue, s => s.RegisterCapital <= input.RegisterCapitalEnd.Value)
//营业额区间查询
.WhereIF(input.TurnOverStart.HasValue, s => s.TurnOver >= input.TurnOverStart.Value)
.WhereIF(input.TurnOverEnd.HasValue, s => s.TurnOver <= input.TurnOverEnd.Value)
.WhereIF(!input.LicenseNo.IsNullOrWhiteSpace(), t => t.LicenseNo.Contains(input.LicenseNo)) //如需要精确匹配则用Equals
.WhereIF(!input.Bank.IsNullOrWhiteSpace(), t => t.Bank.Contains(input.Bank)) //如需要精确匹配则用Equals
.WhereIF(!input.BankAccount.IsNullOrWhiteSpace(), t => t.BankAccount.Contains(input.BankAccount)) //如需要精确匹配则用Equals
.WhereIF(!input.LocalTaxNo.IsNullOrWhiteSpace(), t => t.LocalTaxNo.Contains(input.LocalTaxNo)) //如需要精确匹配则用Equals
.WhereIF(!input.NationalTaxNo.IsNullOrWhiteSpace(), t => t.NationalTaxNo.Contains(input.NationalTaxNo)) //如需要精确匹配则用Equals
.WhereIF(!input.LegalMan.IsNullOrWhiteSpace(), t => t.LegalMan.Contains(input.LegalMan)) //如需要精确匹配则用Equals
.WhereIF(!input.LegalTelephone.IsNullOrWhiteSpace(), t => t.LegalTelephone.Contains(input.LegalTelephone)) //如需要精确匹配则用Equals
.WhereIF(!input.LegalMobile.IsNullOrWhiteSpace(), t => t.LegalMobile.Contains(input.LegalMobile)) //如需要精确匹配则用Equals
.WhereIF(!input.Source.IsNullOrWhiteSpace(), t => t.Source.Contains(input.Source)) //如需要精确匹配则用Equals
.WhereIF(!input.WebSite.IsNullOrWhiteSpace(), t => t.WebSite.Contains(input.WebSite)) //如需要精确匹配则用Equals
.WhereIF(!input.CompanyPictureGUID.IsNullOrWhiteSpace(), t => t.CompanyPictureGUID.Contains(input.CompanyPictureGUID)) //如需要精确匹配则用Equals
.WhereIF(!input.CustomerType.IsNullOrWhiteSpace(), t => t.CustomerType.Contains(input.CustomerType)) //如需要精确匹配则用Equals
.WhereIF(!input.Grade.IsNullOrWhiteSpace(), t => t.Grade.Contains(input.Grade)) //如需要精确匹配则用Equals
.WhereIF(!input.CreditStatus.IsNullOrWhiteSpace(), t => t.CreditStatus.Contains(input.CreditStatus)) //如需要精确匹配则用Equals
.WhereIF(!input.Importance.IsNullOrWhiteSpace(), t => t.Importance.Contains(input.Importance)) //如需要精确匹配则用Equals
.WhereIF(input.IsPublic.HasValue, t => t.IsPublic == input.IsPublic) //如需要精确匹配则用Equals
.WhereIF(input.Satisfaction.HasValue, t => t.Satisfaction == input.Satisfaction) //如需要精确匹配则用Equals
.WhereIF(!input.Note.IsNullOrWhiteSpace(), t => t.Note.Contains(input.Note)) //如需要精确匹配则用Equals
.WhereIF(input.TransactionCount.HasValue, t => t.TransactionCount == input.TransactionCount) //如需要精确匹配则用Equals //交易金额区间查询
.WhereIF(input.TransactionTotalStart.HasValue, s => s.TransactionTotal >= input.TransactionTotalStart.Value)
.WhereIF(input.TransactionTotalEnd.HasValue, s => s.TransactionTotal <= input.TransactionTotalEnd.Value)
//首次交易时间区间查询
.WhereIF(input.TransactionFirstDayStart.HasValue, s => s.TransactionFirstDay >= input.TransactionFirstDayStart.Value)
.WhereIF(input.TransactionFirstDayEnd.HasValue, s => s.TransactionFirstDay <= input.TransactionFirstDayEnd.Value)
//最近交易时间区间查询
.WhereIF(input.TransactionLastDayStart.HasValue, s => s.TransactionLastDay >= input.TransactionLastDayStart.Value)
.WhereIF(input.TransactionLastDayEnd.HasValue, s => s.TransactionLastDay <= input.TransactionLastDayEnd.Value)
//最近联系日期区间查询
.WhereIF(input.LastContactDateStart.HasValue, s => s.LastContactDate >= input.LastContactDateStart.Value)
.WhereIF(input.LastContactDateEnd.HasValue, s => s.LastContactDate <= input.LastContactDateEnd.Value) //创建时间区间查询
.WhereIF(input.CreateTimeStart.HasValue, s => s.CreateTime >= input.CreateTimeStart.Value)
.WhereIF(input.CreateTimeEnd.HasValue, s => s.CreateTime <= input.CreateTimeEnd.Value)
//编辑时间区间查询
.WhereIF(input.EditTimeStart.HasValue, s => s.EditTime >= input.EditTimeStart.Value)
.WhereIF(input.EditTimeEnd.HasValue, s => s.EditTime <= input.EditTimeEnd.Value) .WhereIF(!input.Stage.IsNullOrWhiteSpace(), t => t.Stage.Contains(input.Stage)) //如需要精确匹配则用Equals
.WhereIF(!input.Status.IsNullOrWhiteSpace(), s => s.Status == input.Status)
.WhereIF(!input.Creator.IsNullOrWhiteSpace(), t => t.Creator.Contains(input.Creator)) //如需要精确匹配则用Equals
.WhereIF(!input.Editor.IsNullOrWhiteSpace(), t => t.Editor.Contains(input.Editor)) //如需要精确匹配则用Equals
.WhereIF(input.Deleted.HasValue, s => s.Deleted == input.Deleted)
.WhereIF(!input.Dept_ID.IsNullOrWhiteSpace(), t => t.Dept_ID.Contains(input.Dept_ID)) //如需要精确匹配则用Equals
.WhereIF(!input.Company_ID.IsNullOrWhiteSpace(), t => t.Company_ID.Contains(input.Company_ID)) //如需要精确匹配则用Equals
.WhereIF(!input.MarkColor.IsNullOrWhiteSpace(), t => t.MarkColor.Contains(input.MarkColor)) //如需要精确匹配则用Equals
.WhereIF(!input.ShareUsers.IsNullOrWhiteSpace(), t => t.ShareUsers.Contains(input.ShareUsers)) //如需要精确匹配则用Equals
; return query;
}

有了这个丰富条件的处理,我们就可以在前端进行属性赋值就可以了,简单的调用后端通用的接口查询即可。

//构建分页的条件和查询条件
pagerDto = new CustomerPagedDto(this.winGridViewPager1.PagerInfo)
{
//添加所需条件
NameOrCode = this.txtCustomerNo.Text.Trim(),
Deleted = 0
};

查询获得接口数据处理如下代码所示。

var result = await BLLFactory<ICustomerService>.Instance.GetListAsync(pagerDto);
return result;

在分页列表中展示获得的记录详细信息如下代码所示。

/// <summary>
/// 绑定列表数据
/// </summary>
private async void BindData()
{
//entity
this.winGridViewPager1.DisplayColumns = displayColumns;
this.winGridViewPager1.ColumnNameAlias = await BLLFactory<ICustomerService>.Instance.GetColumnNameAlias();//字段列显示名称转义 //获取分页数据列表
var result = await GetData(); //设置所有记录数和列表数据源
this.winGridViewPager1.PagerInfo.RecordCount = result.TotalCount; //需先于DataSource的赋值,更新分页信息
this.winGridViewPager1.DataSource = result.Items;
this.winGridViewPager1.PrintTitle = "客户信息列表";
}

3、对于多种属性、状态条件的统一处理

我在之前介绍过的CRM系统主界面中,关于客户关系信息的展示的时候,是通过一个复杂的树形列表来承载不同属性来进行快速的查询,如下界面所示。

这些树形列表的属性信息,在SqlSugar开发框架中,我们统一进行生成,首先定义一个通用的承载对象,如下类所示。

/// <summary>
/// 对CRM的业务数据进行统计的一个公共类
/// </summary>
public class CrmStaticsDto
{
/// <summary>
/// 节点显示名称
/// </summary>
public string Label { get; set; } /// <summary>
/// 属性名称
/// </summary>
public string TypeName { get; set; } /// <summary>
/// 数量
/// </summary>
public long Count { get; set; } /// <summary>
/// 业务分类
/// </summary>
public string Category { get; set; } /// <summary>
/// 记录的日期开始
/// </summary>
public DateTime? DateStart { get; set; }
/// <summary>
/// 记录的日期结束
/// </summary>
public DateTime? DateEnd { get; set; } /// <summary>
/// 创建人信息
/// </summary>
public CListItem Creator { get; set; } /// <summary>
/// 子节点集合
/// </summary>
public List<CrmStaticsDto> children { get; set; } = new List<CrmStaticsDto>();
}

这个类似一个嵌套的集合,通过children进行添加更多的子集记录。

后端提供一个获取统计信息的树形列表的方法,如下定义所示。

        /// <summary>
/// 获取列表统计信息
/// </summary>
/// <returns></returns>
public async Task<List<CrmStaticsDto>> GetStatics(string compnayId)
{
................
}

但我们为它添加各种属性的时候,设置相关的节点文本、类别信息即可。

    //所有记录
var allNode = new CrmStaticsDto()
{
Label = "所有记录"
};
list.Add(allNode); var propertyNode = new CrmStaticsDto()
{
Label = "客户属性分类"
};
list.Add(propertyNode); var typeName = "客户状态";
var count = await baseQuery.Clone().CountAsync();//Clone()避免进行多次查询时,可能会出现结果不正确的问题
var statusNode = new CrmStaticsDto()
{
Label = $"{typeName}({count})",
Count = count,
TypeName = typeName
};
var dict = await dictDataService.FindByDictType(typeName);
foreach (var info in dict)
{
var value = info.Value;
var subCount = baseQuery.Clone().Where(s => s.Status == value).Count();
statusNode.children.Add(new CrmStaticsDto()
{
Label = $"{info.Name}({subCount})",
Count = subCount,
Category = info.Value,
TypeName = typeName
});
}
propertyNode.children.Add(statusNode);

这样我们在前端的WInform界面中展示树形列表的时候,就会变得非常简单,通过一个递归的函数就可以添加相关的节点信息了,如下代码所示。

private async void InitTree()
{
this.treeView1.BeginUpdate();
this.treeView1.Nodes.Clear(); //获取所有的统计列表
var staticsList = await BLLFactory<ICustomerService>.Instance.GetStatics(this.SelectedCompanyID);
await AddTreeData(staticsList, null);
//this.treeView1.ExpandAll();
this.treeView1.EndUpdate();
} private async Task AddTreeData(List<CrmStaticsDto> staticsList, TreeNode parentNode = null)
{
var i = 0;
if (staticsList != null)
{
foreach (var info in staticsList)
{
var node = new TreeNode(info.Label, i, i);
node.Tag = info;
node.Text = info.Label; await AddTreeData(info.children, node); if (parentNode == null)
{
this.treeView1.Nodes.Add(node); //如果是顶级处理,则treeView1节点加入
}
else
{
parentNode.Nodes.Add(node); //如果是递归的,则加到父节点上
}
}
}
}

以上就是对联合多个表进行查询以及树形列表的条件展示的处理思路,系统能够给大家一些参考思路。

基于SqlSugar的开发框架循序渐进介绍(31)-- 在查询接口中实现多表联合和单表对象的统一处理的更多相关文章

  1. 基于SqlSugar的开发框架循序渐进介绍(3)-- 实现代码生成工具Database2Sharp的整合开发

    我喜欢在一个项目开发模式成熟的时候,使用代码生成工具Database2Sharp来配套相关的代码生成,对于我介绍的基于SqlSugar的开发框架,从整体架构确定下来后,我就着手为它们量身定做相关的代码 ...

  2. 基于SqlSugar的开发框架循序渐进介绍(4)-- 在数据访问基类中对GUID主键进行自动赋值处理

    我们在设计数据库表的时候,往往为了方便,主键ID一般采用字符串类型或者GUID类型,这样对于数据库表记录的迁移非常方便,而且有时候可以在处理关联记录的时候,提前对应的ID值.但有时候进行数据记录插入的 ...

  3. 基于SqlSugar的开发框架循序渐进介绍(5)-- 在服务层使用接口注入方式实现IOC控制反转

    在前面随笔,我们介绍过这个基于SqlSugar的开发框架,我们区分Interface.Modal.Service三个目录来放置不同的内容,其中Modal是SqlSugar的映射实体,Interface ...

  4. 基于SqlSugar的开发框架循序渐进介绍(6)-- 在基类接口中注入用户身份信息接口

    在基于SqlSugar的开发框架中,我们设计了一些系统服务层的基类,在基类中会有很多涉及到相关的数据处理操作的,如果需要跟踪具体是那个用户进行操作的,那么就需要获得当前用户的身份信息,包括在Web A ...

  5. 基于SqlSugar的开发框架循序渐进介绍(8)-- 在基类函数封装实现用户操作日志记录

    在我们对数据进行重要修改调整的时候,往往需要跟踪记录好用户操作日志.一般来说,如对重要表记录的插入.修改.删除都需要记录下来,由于用户操作日志会带来一定的额外消耗,因此我们通过配置的方式来决定记录那些 ...

  6. 基于SqlSugar的开发框架循序渐进介绍(12)-- 拆分页面模块内容为组件,实现分而治之的处理

    在早期的随笔就介绍过,把常规页面的内容拆分为几个不同的组件,如普通的页面,包括列表查询.详细资料查看.新增资料.编辑资料.导入资料等页面场景,这些内容相对比较独立,而有一定的代码量,本篇随笔介绍基于V ...

  7. 基于SqlSugar的开发框架循序渐进介绍(13)-- 基于ElementPlus的上传组件进行封装,便于项目使用

    在我们实际项目开发过程中,往往需要根据实际情况,对组件进行封装,以更简便的在界面代码中使用,在实际的前端应用中,适当的组件封装,可以减少很多重复的界面代码,并且能够非常简便的使用,本篇随笔介绍基于El ...

  8. 基于SqlSugar的开发框架循序渐进介绍(14)-- 基于Vue3+TypeScript的全局对象的注入和使用

    刚完成一些前端项目的开发,腾出精力来总结一些前端开发的技术点,以及继续完善基于SqlSugar的开发框架循序渐进介绍的系列文章,本篇随笔主要介绍一下基于Vue3+TypeScript的全局对象的注入和 ...

  9. 基于SqlSugar的开发框架循序渐进介绍(15)-- 整合代码生成工具进行前端界面的生成

    在前面随笔<基于SqlSugar的开发框架循序渐进介绍(12)-- 拆分页面模块内容为组件,实现分而治之的处理>中我们已经介绍过,对于相关的业务表的界面代码,我们已经尽可能把不同的业务逻辑 ...

  10. 基于SqlSugar的开发框架循序渐进介绍(17)-- 基于CSRedis实现缓存的处理

    在一个应用系统的开发框架中,往往很多地方需要用到缓存的处理,有些地方是为了便于记录用户的数据,有些地方是为了提高系统的响应速度,如有时候我们在发送一个短信验证码的时候,可以在缓存中设置几分钟的过期时间 ...

随机推荐

  1. dart基础---->单例singleton

    At least, there are three ways to create the singleton object with dart. 1. factory constructor clas ...

  2. 推荐三款 Mac 上的理财神器 iCompta、Rublik、UctoX

    今天推荐三款理财神器,像个人的话可以使用 iCompta(个人财务管理)一款软件就好了,但有些朋友可能有关注汇率的需求,可以使用 Rublik(汇率动态),还有一些小伙伴可能有自己的公司等原因财务量较 ...

  3. Mac 音频转换器推荐 DRmare Audio Converter、Audi Free Auditor

    给大家推荐两款 Mac 上的音频转换器,这两款转换器都可以转换苹果音乐,iTunes歌曲或者一些常规的音轨到MP3, FLAC, WAV, M4A, AAC格式等等,转换后我们就可以在所有的设备和播放 ...

  4. Spring注解系列——@PropertySource

    在Spring框架中@PropertySource注解是非常常用的一个注解,其主要作用是将外部化配置解析成key-value键值对"存入"Spring容器的Environment环 ...

  5. [Linux]常用命令之【du/fdisk/df/ls】#磁盘管理/文件管理#

    本文的经典应用场景: 1.查找占用磁盘存储空间最大的目录/文件 2.关于[磁盘分区]的相关概念和实操,详见另一博文:[Linux]磁盘分区 - 博客园/千千寰宇 1 fdisk fdisk := &q ...

  6. 循序渐进的掌握uni-app,两个小时完成一个简单项目——新闻App、新闻小程序

    效果图 一.创建项目 uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS.Android.Web(响应式).以及各种小程序(微信/支付宝/百度/头条/ ...

  7. RCE-Tricks

    这篇文章介绍RCE的一些tricks 0x01 无回显的RCE 在ctf中,有时会遇到无回显rce,就是说虽然可以进行命令执行,但却看不到命令执行的结果,也不知道命令是否被执行,借着这次总结rce的机 ...

  8. 【kafka】-分区-消费端负载均衡

    一.为什么kafka要做分区? 因为当一台机器有可能扛不住(类比:就像redis集群中的redis-cluster一样,一个master抗不住写,那么就多个master去抗写),把一个队列的单一mas ...

  9. 沁恒 CH32V208(一): CH32V208WBU6 评估板上手报告和Win10环境配置

    目录 沁恒 CH32V208(一): CH32V208WBU6 评估板上手报告和Win10环境配置 CH32V208 CH32V208系列是沁恒32位RISC-V中比较新的一个系列, 基于青稞RISC ...

  10. Tomacat乱码和报错UTF-8 序列的字节 2 无效和‘application/json;charset=UTF-8‘ not supported的处理

    文章目录 前言 1. tomcat乱码的处理方法 2. applicationContext.xml报错2 字节的 UTF-8 序列的字节 2 无效 3. 报错'application/json;ch ...