在做一些常規應用的時候,我們往往需要確定條件的內容,以便在後臺進行區分的進行精確查詢,在移動端,由於受限於屏幕界面的情況,一般會對多個指定的條件進行模糊的搜索,而這個搜索的處理,也是和前者強類型的條件查詢處理類似的處理過程,因此本篇隨筆探討兩種不同查詢在前端界面上的展示效果,以及後端基於.netCo... ...
在做一些常規應用的時候,我們往往需要確定條件的內容,以便在後臺進行區分的進行精確查詢,在移動端,由於受限於屏幕界面的情況,一般會對多個指定的條件進行模糊的搜索,而這個搜索的處理,也是和前者強類型的條件查詢處理類似的處理過程,因此本篇隨筆探討兩種不同查詢在前端界面上的展示效果,以及後端基於.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的移動端實現多條件查詢的處理》

轉載請註明出處:撰寫人:伍華聰 http://www.iqidi.com