基于SqlSugar的开发框架循序渐进介绍(20)-- 在基于UniApp+Vue的移动端实现多条件查询的处理

基于,sqlsugar,开发,框架,循序渐进,介绍,uniapp,vue,移动,实现,条件,查询,处理 · 浏览次数 : 1444

小编点评

## 基于SqlSugar的开发框架循序渐进介绍 **1.框架基础类的设计和使用** * 基类Service层用于定义通用方法,如模糊查询、排序等。 * 业务类继承BaseApi类,实现特定业务逻辑。 **2.自定义条件处理** * 创建FilteredQueryAsync方法,根据Filter进行模糊查询。 * 在Service层使用接口注入方式,实现IOC控制反转。 **3.代码生成工具Database2Sharp的整合开发** * 可以生成Vue3+TypeScript的前端界面和Winform端界面。 * 使用数据库2sharp工具,快速生成代码。 **4.在数据访问基类中对GUID主键进行自动赋值处理** * 可以避免手动处理GUID主键,提升数据访问效率。 **5.在服务层使用接口注入方式实现IOC控制反转** * 可以使用接口注入,将不同的业务逻辑注入到服务层中。 **6.在基类接口中注入用户身份信息接口** * 可以方便在不同业务层中获取用户身份信息。 **7.在文件上传模块中采用选项模式【Options】处理常规上传和FTP文件上传** * 可以根据不同的上传类型选择合适的选项模式。 **8.利用axios组件的封装,实现对后端API数据的访问和基类的统一封装处理** * 可以方便在多个业务层中访问后端API。 **9.使用TypeScript和Vue3的Setup语法糖编写页面和组件的总结** * 可以缩短页面编写,提升代码可读性。 **10.使用TypeScript和Vue3的Setup语法糖编写页面和组件的总结** * 可以缩短页面编写,提升代码可读性。 **11.使用TypeScript和Vue3的Setup语法糖编写页面和组件的总结** * 可以缩短页面编写,提升代码可读性。 **12.拆分页面模块内容为组件,实现分而治之的处理** * 可以将页面模块拆分,提高代码可维护性。 **13.基于ElementPlus的上传组件进行封装,便于项目使用** * 可以将上传组件封装,便于项目使用。 **14. 基于Vue3+TypeScript的全局对象的注入和使用** * 可以方便在多个页面中使用全局对象。 **15.使用TypeScript和Vue3的Setup语法糖编写页面和组件的总结** * 可以缩短页面编写,提升代码可读性。 **16.整合代码生成工具进行前端界面的生成** * 可以快速生成前端界面代码。 **17.工作流模块的功能介绍** * 可以展示工作流程,帮助用户理解代码逻辑。 **18. 基于CSRedis实现缓存的处理** * 可以提升数据访问效率,降低用户延迟。 **19. 基于代码生成工具Database2Sharp,快速生成Vue3+TypeScript的前端界面和Winform端界面** * 可以快速生成代码,提升开发效率。 **20. 基于UniApp+Vue的移动前端的功能介绍** * 可以实现移动前端的功能,如多条件查询等。

正文

在做一些常规应用的时候,我们往往需要确定条件的内容,以便在后台进行区分的进行精确查询,在移动端,由于受限于屏幕界面的情况,一般会对多个指定的条件进行模糊的搜索,而这个搜索的处理,也是和前者强类型的条件查询处理类似的处理过程,因此本篇随笔探讨两种不同查询在前端界面上的展示效果,以及后端基于.netCore的Web API端的基类进行的统一封装处理。

1、前端精确条件的查询处理

在基于Vue3+Typescript+ElementPlus的前端界面中,查询是很多界面需要拥有的功能,如下所示。 

 展开后的全部查询条件

 

 以上的查询部分是一个查询函数的处理,如下代码所示。

// 查询列表处理
async function search() {
  pageInfo.pageIndex = 1; // 重置为第一页

  //默认使用当前用户公司
  const userInfo = $u.util.storageSession.getItem('user_info');
  searchForm.company_ID = userInfo?.company_ID; //所属公司
  await getlist(); //获取列表
}

//列表数据获取
async function getlist() {
  loading.value = true;
  var param = {
    // 分页条件
    SkipCount: (pageInfo.pageIndex - 1) * pageInfo.pageSize,
    MaxResultCount: pageInfo.pageSize,
    Sorting: sorting.value,
// 查询过滤条件 Name: searchForm.name, MobilePhone: searchForm.mobilePhone, Email: searchForm.email, QQ: searchForm.qq, Nickname: searchForm.nickname, HandNo: searchForm.handNo, IsExpire: searchForm.isExpire, Title: searchForm.title, dept_ID: searchForm.dept_id, company_ID: searchForm.company_ID }; //日期条件处理 addDateRange(param, searchForm.creationTime); let result = await user.GetList(param); if (result) { list.value = result.items; pageInfo.totalCount = result.totalCount; } setTimeout(() => { loading.value = false; }, 500); }

我们看到,这些条件都是由特定的参数组成的,因此他们是精确性的属性查询。

前端根据框架后端的接口进行前端JS端的类的封装处理,引入了ES6类的概念实现业务基类接口的统一封装,简化代码。

权限模块我们涉及到的用户管理、机构管理、角色管理、菜单管理、功能管理、操作日志、登录日志等业务类,那么这些类继承BaseApi,就会具有相关的接口了,如下所示继承关系。

按照这个思路,我们在BaseApi的ES6类里面定义了对应Web API基类里面的操作方法,如下所示。

 这样,我们在创建一个业务类的时候,如果没有特殊的自定义接口,只需要继承基类BaseApi即可具有所有的常规基类方法了。

 我们再来后端看看具体的查询逻辑实现,首先需要了解各个控制器之间的继承关系,如下图所示 。

同样,我们基础的查询处理逻辑,主要也是放在BusinessController里面实现,毕竟是通用的逻辑,变化的只是一些实体信息,因此可以通过泛型的模板方法设计模式处理变化的部分。 

 

 我们可以看到,在BusinessController控制器部分,它也只是对Service层逻辑的简单封装一下,核心的处理逻辑部分,在下面的基类Service层的代码中。

/// <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
   );
}

这里基类Service层主要处理逻辑部分,而具体的构建精确的查询处理条件,下放在了每个具体业务Service类中进行处理了。

UserService是具体对应的业务类的逻辑处理层,该类的定义方法如下所示。

    /// <summary>
    /// 应用层服务接口实现
    /// </summary>
    public class UserService : MyCrudService<UserInfo, int, UserPagedDto>, IUserService

下放在UserService这个具体业务的Service类中的查询处理逻辑,这部分通过代码生成工具生成即可。

/// <summary>
/// 自定义条件处理
/// </summary>
/// <param name="input">查询条件Dto</param>
/// <returns></returns>
protected override ISugarQueryable<UserInfo> CreateFilteredQueryAsync(UserPagedDto input)
{
    var query = base.CreateFilteredQueryAsync(input);
    query = query
        .WhereIF(input.ExcludeId.HasValue, t => t.Id != input.ExcludeId) //不包含排除ID
        .WhereIF(input.PID.HasValue, s => s.PID == input.PID)
        .WhereIF(!input.HandNo.IsNullOrWhiteSpace(), t => t.HandNo.Contains(input.HandNo)) //如需要精确匹配则用Equals
        .WhereIF(!input.Name.IsNullOrWhiteSpace(), t => t.Name.Contains(input.Name)) //如需要精确匹配则用Equals
        .WhereIF(!input.FullName.IsNullOrWhiteSpace(), t => t.FullName.Contains(input.FullName)) //如需要精确匹配则用Equals
        .WhereIF(!input.Nickname.IsNullOrWhiteSpace(), t => t.Nickname.Contains(input.Nickname)) //如需要精确匹配则用Equals
        .WhereIF(input.IsExpire.HasValue, t => t.IsExpire == input.IsExpire) //如需要精确匹配则用Equals
        
        //过期时间区间查询
        .WhereIF(input.ExpireDateStart.HasValue, s => s.ExpireDate >= input.ExpireDateStart.Value)
        .WhereIF(input.ExpireDateEnd.HasValue, s => s.ExpireDate <= input.ExpireDateEnd.Value)
         
        ****//此处省略更多其他条件
        ;
    return query;
}

通过逻辑和具体对象的实现分离,从而构建了很多通用的基类函数,这些函数只需要在子类重写一些规则即可实现更加详细的处理,也称为模板方法的设计模式,这种方式广泛应用于基类函数的抽象处理。

 

2、前端模糊查询及自定义查询的处理

介绍了前面基于Vue3+Typescript+ElementPlus的前端界面的内容,主要还是用来引出基于UniApp+Vue的移动端实现多条件查询的处理,一般移动端的界面空间比较宝贵,所以往往查询通过组合条件的方式进行模糊查询处理,如下界面所示。

 在查询框中输入一些条件,会在后端对多个条件进行模糊匹配,并返回相应的结果列表进行展示,如下所示。

 

查询界面只是接受了一个输入值,通过传递该值,在后端进行多字段的匹配查询处理。前端界面如下所示。

async getlist() {
    var params = {
        MaxResultCount: this.pageSize,
        SkipCount: (this.pageIndex - 1) * this.pageSize,
        Sorting: '',
    }
    if (this.isAdvance) {
        let {
            startDate,
            endDate,
            filter,
            deliveryArea,
            line
        } = this.advanceData;
        params.TimeStart = startDate
        params.TimeEnd = endDate
        params.DeliveryAreas = deliveryArea
        params.Lines = line
        params.Filter = filter
    } else {
        params.Filter = this.searchValue;
    }
    console.log(params)

    this.loadding = true;
    this.pullUpOn = true;

    let res = {};
    if (this.isAdvance) {
        res = await sign.GetAllByFilter2(params);
    } else {
        res = await sign.GetAllByFilter(params);
    }
    console.log(res)
    if (this.totalCount == res.totalCount) {
        this.hasmore = false; //没有了
        this.loadding = false;
        this.pullUpOn = false;
        uni.stopPullDownRefresh();
        return;
    }

    this.totalCount = res.totalCount;
    let items = res.items;
    for (var i = 0; i < items.length; i++) {
        this.list.push(items[i]);
    }

    if (this.list.length < res.totalCount) {
        this.pageIndex += 1;
        console.log(res.totalCount)
    } else {
        this.hasmore = false; //没有了
    }

    this.loadding = false;
    this.pullUpOn = false
    uni.stopPullDownRefresh();

    let count = items.length;
    let options = {
        msg: `刷新成功,为你更新了${count}条数据`,
        duration: 2000,
        type: "translucent"
    };
    if (this.pageIndex > 1) {
        setTimeout(() => {
            this.$refs.toast.showTips(options);
        }, 300);
    }
},

有时候,如需要精确一些的条件处理,也可以以自定义条件的方式进行查询处理的界面。

 单击【筛选】按钮进入抽屉式的展示页面,弹出高级查询的相关字段属性,可以进行一定的条件设置处理。

同样我们在UniApp+Vue的移动前端项目上,也需要设置BaseApi的基础接口,如下所示。

 而我们的业务类 Sign-Receipt(Sign-Receipt.js )只需要继承BaseApi(base-api.js)类即可,如下所示。

import BaseApi from '@/api/base-api'

// 业务类自定义接口实现, 通用的接口已经在BaseApi中定义
class Api extends BaseApi {
    FindByCode(shopCode) { // GET 根据客户代码获取记录
        var params = {
            shopCode
        };
        return this.httpget(this.baseurl + 'Find-ByCode', params)
    }

    GetAllByFilter2(params) { // 根据条件获取所有记录
        var url = this.baseurl + 'list-filter2';
        return this.httpget(url, params)
    }
}

// 构造接口对象信息 Api实例,并传递业务类接口地址
export default new Api('/api/SignReceipt/')

对应的后端接口,同样也是使用前面介绍精确查询的方式进行处理,在基类Service层里面,有对应通用的模糊查询方法定义。

/// <summary>
/// 根据指定的Filter值分页获取列表
/// </summary>
/// <param name="input">分页查询条件</param>
/// <returns></returns>
public virtual async Task<PagedResultDto<TEntity>> GetListByFilterAsync(PagedSortedAndFilteredInputDto input)
{
    var query = CreateFilteredQueryAsync(input.Filter);
    var totalCount = await query.CountAsync();

    //排序处理
    if (!input.Sorting.IsNullOrWhiteSpace())
    {
        query = query.OrderBy(input.Sorting);
    }
    else
    {
        query = ApplyDefaultSorting(query);
    }

    //分页处理
    query = query.Skip(input.SkipCount).Take(input.MaxResultCount);

    var list = await query.ToListAsync();
    return new PagedResultDto<TEntity>(
       totalCount,
       list
   );
}

那么下放给子类的CreateFilteredQueryAsync 函数就是实现逻辑的关键,毕竟基类是无法构建正确的条件的。

而对应的SignReceiptService类中,是业务类的逻辑处理方法,该类的定义方法如下所示

    /// <summary>
    /// 拍照签收 应用层服务接口实现
    /// </summary>
    public class SignReceiptService : MyCrudService<SignReceiptInfo,string, SignReceiptPagedDto>, ISignReceiptService

因此它里面可以重写模糊查询条件的逻辑,如下代码所示。

/// <summary>
/// 自定义条件处理(根据Filter进行的过滤处理)
/// </summary>
/// <param name="filter">查询条件Dto</param>
/// <returns></returns>
protected override ISugarQueryable<SignReceiptInfo> CreateFilteredQueryAsync(string filter)
{
    var query = base.CreateFilteredQueryAsync(filter);
    query = query.WhereIF(!filter.IsNullOrWhiteSpace(), t => //模糊搜索用Contains, 如需要精确匹配则用Equals
         t.ShopCode.Contains(filter) || t.ShopName.Contains(filter) || t.Line.Contains(filter) ||
         t.DeliveryArea.Contains(filter) || t.SignMan.Contains(filter) || t.DeliverName.Contains(filter) || t.Note.Contains(filter)
         );

    return query;
}

有了这些条件的定义,我们就可以在Web API的后端,对前端的参数进行联合的模糊查询处理,从而为移动前端提供更好的查询接口服务。

而对于高级查询的处理,我们先要定义好对应的通用的实体类信息,如下所示。

然后在具体的进行处理查询逻辑即可,这部分和前面的逻辑处理类似,只是无法实现基类通用的处理而已,因此下发到具体的业务类进行定义。

 最后在控制器部分,进行一个简单的封装处理即可。

  以上就是基于不同前端,包括基于Vue3+Typescript+ElementPlus的前端界面,以及基于UniApp+Vue的移动端界面,实现一些常见查询的处理,前端和后端的配合处理逻辑。

 

系列文章:

基于SqlSugar的开发框架的循序渐进介绍(1)--框架基础类的设计和使用

基于SqlSugar的开发框架循序渐进介绍(2)-- 基于中间表的查询处理

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

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

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

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

基于SqlSugar的开发框架循序渐进介绍(7)-- 在文件上传模块中采用选项模式【Options】处理常规上传和FTP文件上传

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

基于SqlSugar的开发框架循序渐进介绍(9)-- 结合Winform控件实现字段的权限控制

基于SqlSugar的开发框架循序渐进介绍(10)-- 利用axios组件的封装,实现对后端API数据的访问和基类的统一封装处理

基于SqlSugar的开发框架循序渐进介绍(11)-- 使用TypeScript和Vue3的Setup语法糖编写页面和组件的总结

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

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

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

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

基于SqlSugar的开发框架循序渐进介绍(16)-- 工作流模块的功能介绍

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

 《基于SqlSugar的开发框架循序渐进介绍(18)-- 基于代码生成工具Database2Sharp,快速生成Vue3+TypeScript的前端界面和Winform端界面

基于SqlSugar的开发框架循序渐进介绍(19)-- 基于UniApp+Vue的移动前端的功能介绍

基于SqlSugar的开发框架循序渐进介绍(20)-- 在基于UniApp+Vue的移动端实现多条件查询的处理

 

与基于SqlSugar的开发框架循序渐进介绍(20)-- 在基于UniApp+Vue的移动端实现多条件查询的处理相似的内容:

基于SqlSugar的开发框架循序渐进介绍(20)-- 在基于UniApp+Vue的移动端实现多条件查询的处理

在做一些常规应用的时候,我们往往需要确定条件的内容,以便在后台进行区分的进行精确查询,在移动端,由于受限于屏幕界面的情况,一般会对多个指定的条件进行模糊的搜索,而这个搜索的处理,也是和前者强类型的条件查询处理类似的处理过程,因此本篇随笔探讨两种不同查询在前端界面上的展示效果,以及后端基于.netCore的Web API端的基类进行的统一封装处理。

基于SqlSugar的开发框架循序渐进介绍(16)-- 工作流模块的功能介绍

工作流是集成系统的模块应用,使用权限管理系统的身份认证登录后即可使用。本篇随笔介绍工作流模块的界面功能效果。

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

在一个应用系统的开发框架中,往往很多地方需要用到缓存的处理,有些地方是为了便于记录用户的数据,有些地方是为了提高系统的响应速度,如有时候我们在发送一个短信验证码的时候,可以在缓存中设置几分钟的过期时间,这样验证短信验证码的时候,就会自动判断是否过期了。本篇随笔结合CSRedis的使用,介绍如何实现缓存的初始化及使用的处理。

基于SqlSugar的开发框架循序渐进介绍(18)-- 基于代码生成工具Database2Sharp,快速生成Vue3+TypeScript的前端界面和Winform端界面

我们开发一个系统,在保证风格统一、代码强壮、可读性强等基础上,还能够结合代码生成工具快速开发相关后端,以及各种前端界面的,无疑是非常好的,既保证了项目的代码质量,又能够极大的提高开发效率。代码生成工具Database2Sharp是在完善的开发项目上,抽取出数据变化的部分,通过演绎、归纳、反复演绎和归纳等提炼方式抽取出相关的规则,以工具的方式来快速提高生产率,使得我们在开发各种不同的项目上的时候,能

基于SqlSugar的开发框架循序渐进介绍(19)-- 基于UniApp+Vue的移动前端的功能介绍

在之前的SqlSugar系列随笔中,介绍了很多我们关于SqlSugar的开发框架的内容,SqlSugar的开发框架的目的是多前端应用场景,因此其中会包含各种不同的前端应用,前面介绍了基于DevExpress的Winform的前端应用,以及基于Vue3+TypeScript+ElementPlus的BS前端应用,本篇随笔继续介绍SqlSugar的开发框架的另一个前端应用,基于UniApp+Vue+T

基于SqlSugar的开发框架循序渐进介绍(21)-- 在工作流列表页面中增加一些转义信息的输出,在后端进行内容转换

有时候,为了给前端页面输出内容,有时候我们需要准备和数据库不一样的实体信息,因为数据库可能记录的是一些引用的ID或者特殊字符,那么我们为了避免前端单独的进行转义处理,我们可以在后端进行统一的格式化后再行输出,后端处理可以采用不同的DTO尸体信息,后端对不同的实体进行映射处理即可,也可以采用同一个实体,在SqlSugar实体信息中忽略对应的字段写入实现,本篇随笔介绍后者的处理方式,实现在在工作流列表

基于SqlSugar的开发框架循序渐进介绍(22)-- Vue3+TypeScript的前端工作流模块中实现统一的表单编辑和表单详情查看处理

在工作流页面中,除了特定的业务表单信息外,往往也需要同时展示通用申请单的相关信息,因此在页面设计的时候需要使用一些组件化的概念来实现动态的内容展示处理,本篇随笔介绍Vue3+TypeScript+ElementPus的前端工作流模块中实现统一的表单编辑和表单详情查看处理。

基于SqlSugar的开发框架循序渐进介绍(23)-- Winform端管理系统中平滑增加对Web API对接的需求

在前面随笔介绍的基于SqlSugar的WInform端管理系统中,数据提供者是直接访问数据库的方式,不过窗体界面调用数据接口获取数据的时候,我们传递的是标准的接口,因此可扩展性比较好。我曾经在随笔《基于SqlSugar的开发框架循序渐进介绍(5)-- 在服务层使用接口注入方式实现IOC控制反转》中介绍过,该SqlSugar开发框架本身是基于IOC控制反转的,因此对于接入不同的数据提供者,只需要切换

基于SqlSugar的开发框架循序渐进介绍(24)-- 使用Serialize.Linq对Lambda表达式进行序列化和反序列化

在上篇随笔《基于SqlSugar的开发框架循序渐进介绍(23)-- Winform端管理系统中平滑增加对Web API对接的需求》中介绍了基于一个接口,实现对两种不同接入方式(直接访问数据库实现,基于Web API代理类实现)的处理,由于定义的接口中,我们为了方便,也是用了Lambda表达式的进行一些参数的处理,那么如果在Web API代理类中,Lambda表达式是不能直接传递给Web API的控

基于SqlSugar的开发框架循序渐进介绍(25)-- 基于SignalR实现多端的消息通讯

基于ASP.NET Core SignalR 可以实现客户端和服务器之间进行即时通信。本篇随笔介绍一些SignalR的基础知识,以及结合对SqlSugar的开发框架的支持,实现SignalR的多端处理整合,从而实现Winform客户端,基于Vue3+ElementPlus的BS端整合,后面也可以实现对移动端的SignalR的整合通讯。