標籤:ndt not 處理 設定 都對 utils 編號 eof mis
返回總目錄:ABP+AdminLTE+Bootstrap Table許可權管理系統一期
很多人說ABP不適合高並發大型,有一定的道理,但是我覺得還是可以的,就看架構師的能力了,我之前公司就是ABP絕對百萬資料級項目,是一個線上教育網站,涉及到平台,學院,院系,班級,課程,學生等,一個平台多少大學,一個大學多少院系,一個院系多少班級多少課程,其負責程度一點都不簡單,不說了,那是大神,比我在園子看到絕對大多數架構師都強悍.是我等仰望都對象.但是這不是停下腳步仰望的理由,只會是我們追求更強的腳步.
軟體開發中會有大量機械重複的工作,也有大量重複的代碼,使用者需求越來越高,我們要做出的響應也越來越複雜,這就需要我們去整合更多的東西來應付工作的需要。
每當我們要開發一個新的系統的時候,我們要用到以前用到過的東西,比如mvc,ioc,日誌,資料庫的映射,日誌管理,訊息佇列組件等等。我們更希望把更多時間時間用來處理商務邏輯,而不是花在軟體結構,日誌,容錯等問題。
很多大公司都有自己的基礎架構,自己公司封裝了很多東西,像我們公司的日期組件,彈窗,表格樣式,分頁等等都是已經封裝好了的,再後期開發的時候我們只需要去調用一下就可以了,不需要每個控制項都自己再花時間和精力去封裝。
這節我就來說一下在ABP module-zero基礎上做AdminLTE+Bootstrap Table的系統,算是前面十一節的總結和擴充.
首先我們依舊去官網根據abp模板建立解決方案.勾選上module-zero,然後建立資料庫連接,還原nuget包,然後update-database建立資料庫.
接下來就是建立指令碼更新資料庫了,以上這些都在前面的章節講到了,我就不做累述了,不明白可回去一下第一節.
然後在home控制器下建ActionResult login,添加一個試圖頁面.加上自己的登陸頁面樣式js等,這裡我們就不用mvc的形式再在去請求控制器 了,我們直接請求webapi的登陸方法了.是的就是已經搭好了swagger的然後請求/swagger/ui/index的Account介面..
既然前面講到ABP 對javascript ajax的封裝
var newPerson = { name: ‘Dougles Adams‘, age: 42};abp.ajax({ url: ‘/People/SavePerson‘, data: JSON.stringify(newPerson)}).done(function(data) { abp.notify.success(‘created new person with id = ‘ + data.personId);});
其實這裡我們還可以做一些再次封裝,方便在項目中去使用,就以登陸為例效果如下。
abp.ui.block($(‘#login‘)); var url = "/api/Account"; var login = function (para, ajaxtype,posturl) { return abp.ajax({ url: posturl, type: ajaxtype, async: false, data: JSON.stringify(para) }); }; var loginModel = { "tenancyName": "", "usernameOrEmailAddress": $("#userName").val(), "password": $("#password").val() }; abp.ui.setBusy( $(‘#login‘), login(loginModel, "post", url).done(function (data) { abp.auth.setToken("Bearer " + data); window.location.href = "/admin/userinfo/index" }), );
當然這是在ABP原來封裝的效果上加上的,細心的你已經發現這裡多了兩個東西,一個是abp.ui.block,另外一個是abp.ui.setBusy,這其實是一個阻止使用者重複提交,和正在提交繁忙狀態,
其實就是一個遮罩層。
這裡是ABP整合的jquery.blockUI.js外掛程式,該API使用一個透明的塗層(transparent overlay)來阻塞整個頁面或者該頁面上的一個元素。這樣,使用者的點擊就無效了。當儲存一個表單或者載入一個地區(一個div或者整個頁面)時這是很有用的。比如
另外abpjs中也對blockUI做了一些常用方法的封裝,設定阻塞abp.ui.block,取消阻塞abp.ui.unblock ,設定繁忙狀abp.ui.setBusy 和解除繁忙狀態abp.ui.clearBusy
abp.ui.block = function (elm) { abp.log.warn(‘abp.ui.block is not implemented!‘); }; abp.ui.unblock = function (elm) { abp.log.warn(‘abp.ui.unblock is not implemented!‘); }; /* UI BUSY */ //Defines UI Busy API, not implements it abp.ui.setBusy = function (elm, optionsOrPromise) { abp.log.warn(‘abp.ui.setBusy is not implemented!‘); }; abp.ui.clearBusy = function (elm) { abp.log.warn(‘abp.ui.clearBusy is not implemented!‘); };
abp.ui.block(); //阻塞整個頁面abp.ui.block($(‘#MyDivElement‘)); //可以使用jQuery 選取器..abp.ui.block(‘#MyDivElement‘); //..或者直接使用選取器abp.ui.unblock(); //解除阻塞整個頁面abp.ui.unblock(‘#MyDivElement‘); //解除阻塞特定的元素
UI Block API預設使用jQuery的blockUI外掛程式實現的。要是它生效,你應該包含它的javascript檔案,然後在頁面中包含abp.blockUI.js作為適配器。
另外一個就是busy 該API用於使得某些頁面或者元素處於繁忙狀態。比如,你可能想阻塞一個表單,然後當提交表單至伺服器時展示一個繁忙的指標。例子:
abp.ui.setBusy(‘#MyLoginForm‘);abp.ui.clearBusy(‘#MyLoginForm‘);
效果就是上面的繁忙效果。
該參數應該是一個選取器(如‘#MyLoginForm’)或者jQuery選取器(如$(‘#MyLoginForm‘))。要使得整個頁面處於繁忙狀態,你可以傳入null(或者‘body‘)作為選取器。setBusy函數第二個參數接收一個promise(約定),當該約定完成時會自動清除繁忙的狀態。因為abp.ajax返回promise,我們可以直接將它作為promise傳入。要學習慣於promise更多的東西,查看jQuery的Deferred。
UI Busy API是使用spin.js實現的。要讓它生效,應該包含它的javascript檔案,然後在頁面中包含abp.spin.js作為適配器。
經過上面的努力,我們得登陸也已經做好了。登陸成功之後我們要做事的事情就是一個儲存token另外一個就是路由的重新導向了。
token在ABP中很重要,我們在請求 /api/Account會反饋一個token,我們在登陸的時候就把token存到cookie中,以方便後面的使用。如登陸中的 abp.auth.setToken("Bearer " + data); 那ABP是怎麼樣設定cookie的了,這裡也做了封裝。
abp.auth.tokenCookieName = ‘Abp.AuthToken‘; abp.auth.setToken = function (authToken, expireDate) { abp.utils.setCookieValue(abp.auth.tokenCookieName, authToken, expireDate, abp.appPath); }; abp.auth.getToken = function () { return abp.utils.getCookieValue(abp.auth.tokenCookieName); } abp.auth.clearToken = function () { abp.auth.setToken(); }
這裡面就包含了token常用的存取和清除的方法。
我們在已經添加了域,所以這裡登陸成功之後直接把url指向/admin/userinfo/index。當然在/Areas/Common/Views/Layout裡面我們已經AdminLTE的布局了,包括菜單已經載入出來了,其實現在服務層的時候漏了一些東西,我們這裡補上,ABP既然是一個架構
那麼在建立Service的時候自然要包含基礎增刪查改的方法,那麼這時候IAsyncCrudAppService就派上用場了。這裡我們以模板IModulesService講一下。首先我們建立好model和DTO
using Abp.Domain.Entities;using System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations;using System.Linq;using System.Text;using System.Threading.Tasks;namespace JCms.Meuns{ public class Meun : Entity<int>, IMayHaveTenant { public int? ParentId { get; set; } [Required] [StringLength(20)] public string Name { get; set; } [Required] [StringLength(50)] public string LinkUrl { get; set; } [StringLength(100)] public string Description { get; set; } public bool IsMenu { get; set; } public int Code { get; set; } public bool Enabled { get; set; } public DateTime UpdateDate { get; set; } public int? TenantId { get; set; } }}
DTO:
using Abp.Application.Services.Dto;using Abp.AutoMapper;using Abp.Domain.Entities;using System;using System.Collections.Generic;using System.ComponentModel;using System.ComponentModel.DataAnnotations;using System.Linq;using System.Text;using System.Threading.Tasks;namespace JCms.Meuns{ /// <summary> /// 菜單 /// </summary> [Serializable] [AutoMapFrom(typeof(Meun))] public class MeunDto : EntityDto<int> { /// <summary> /// id /// </summary> public int Id { get; set; } /// <summary> /// 父模組Id /// </summary> public int? ParentId { get; set; } /// <summary> /// 名稱 /// </summary> [Required] [StringLength(20)] public string Name { get; set; } /// <summary> /// 連結地址 /// </summary> [Required] [StringLength(50)] public string LinkUrl { get; set; } /// <summary> /// 是否是菜單 /// </summary> public bool IsMenu { get; set; } /// <summary> /// 模組編號 /// </summary> public int Code { get; set; } /// <summary> /// 描述 /// </summary> [StringLength(100)] public string Description { get; set; } /// <summary> /// 是否啟用 /// </summary> public bool Enabled { get; set; } public DateTime UpdateDate { get; set; } //public virtual MeunDto ParentModule { get; set; } //public List<MeunDto> ChildModules { get; private set; } public List<MeunDto> children { get; set; } }}
這裡要注意的如果model整合了某個介面,那麼DTO也要繼承這個介面的DTO,不然再繼承IAsyncCrudAppService就會報錯。
比如面的model繼承Entity<int> 那麼DTO也要繼承EntityDto<int>.
然後我們看一下IAsyncCrudAppService需要哪麼參數。
這裡都可以看得很清楚了,包括增刪查改的DTO這裡我比較懶,都用了一個。
介面:
public interface IModulesService : IAsyncCrudAppService<MeunDto, int, PagedResultRequestDto, MeunDto, MeunDto> // IApplicationService { }
實現
public class ModulesService : AsyncCrudAppService<Meun, MeunDto, int, PagedResultRequestDto, MeunDto, MeunDto>, IModulesService { public ModulesService(IRepository<Meun, int> repository) : base(repository) { } }
然後,我們在apiJCMSWebApiModule方法下加上.WithConventionalVerbs() 這樣我們就可以看到特定的HTTP首碼,不然全是post,HTTP動詞是通過方法名的首碼決定的:
- Get:方法名以Get開頭。
- Put:方法名以Put或Update開頭。
- Delete:方法名以Delete或Remove開頭。
- Post:方法名以Post或Create開頭。
- 否則,Post是HTTP動詞的預設值。
我們可以通過對特定的方法使用WithVerb方法或者HTTP特性來覆蓋上述慣例。
就這樣,我們在業務層中常用的增刪改查的方法就誕生了。
驗證一下,傳入參數,結果沒毛病,可用。當然這雷根據自己的需要可以重寫這些方法的。頁面和前面的頁面差不多,沒啥講的,這裡頁面增刪改查都已經實現。
現在使用者管理和角色管理功能已經實現,後面我會再做菜單管理,授權管理,做完基本上就完了,當然後面的也是重點。共同努力!
github 地址:https://github.com/Jimmey-Jiang/JCMS
返回總目錄:ABP+AdminLTE+Bootstrap Table許可權管理系統一期
ABP module-zero +AdminLTE+Bootstrap Table+jQuery許可權管理系統第十二節--小結,Bootstrap Table之角色管理